التحويل الإجباري باستخدام as! ومخاطره
استخدم as! فقط عندما يكون نجاح التحويل مضمونًا.
التحويل الإجباري باستخدام as! ومخاطره درس مجاني في Swift Academy على CoddyKit. هذا هو الدرس 3 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Swift Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Swift Academy 4 دروس في المجموع.
التحويل القسري
يُجري معامل التحويل القسري as! تحويلًا تنازليًا ويفك التغليف في خطوة واحدة. ويمنحك النوع غير الاختياري مباشرةً، لكنه يتسبب في انهيار البرنامج إذا فشل التحويل.
class Animal {
let name: String
init(name: String) { self.name = name }
}
class Dog: Animal {
func bark() -> String { return name + " says Woof" }
}
class Cat: Animal {
func meow() -> String { return name + " says Meow" }
}
let a: Animal = Dog(name: "Rex")
let dog = a as! Dog
print(dog.bark())من دون تغليف اختياري
بخلاف as?، تكون نتيجة as! من النوع العادي وليست قيمة اختيارية. لذلك لا يوجد شيء لفك تغليفه.
class Animal {
let name: String
init(name: String) { self.name = name }
}
class Dog: Animal {
func bark() -> String { return name + " says Woof" }
}
class Cat: Animal {
func meow() -> String { return name + " says Meow" }
}
let a: Animal = Dog(name: "Rex")
let dog: Dog = a as! Dog
print(type(of: dog))خطر استخدام as!
إذا لم يكن المثيل من النوع الهدف فعلًا، يتسبب as! في خطأ وقت التشغيل ويوقف البرنامج. ولا توجد طريقة للتعافي من ذلك.
class Animal {
let name: String
init(name: String) { self.name = name }
}
class Dog: Animal {
func bark() -> String { return name + " says Woof" }
}
class Cat: Animal {
func meow() -> String { return name + " says Meow" }
}
let a: Animal = Dog(name: "Rex")
// let cat = a as! Cat // would crash at runtime
print("Only force-cast when certain")متى يكون التحويل القسري آمنًا
استخدم as! فقط عندما تكون متأكدًا تمامًا من النوع، مثلًا مباشرةً بعد التحقق باستخدام is.
class Animal {
let name: String
init(name: String) { self.name = name }
}
class Dog: Animal {
func bark() -> String { return name + " says Woof" }
}
class Cat: Animal {
func meow() -> String { return name + " says Meow" }
}
let a: Animal = Dog(name: "Rex")
if a is Dog {
let dog = a as! Dog
print(dog.bark())
}التحويل القسري بعد ضمان النوع
إذا كان منطق الشيفرة يضمن النوع، فإن التحويل القسري يوثق هذا اليقين. ومع ذلك، فضّل as? عندما لا تكون متأكدًا.
class Animal {
let name: String
init(name: String) { self.name = name }
}
class Dog: Animal {
func bark() -> String { return name + " says Woof" }
}
class Cat: Animal {
func meow() -> String { return name + " says Meow" }
}
func barkIfDog(_ a: Animal) {
guard a is Dog else { return }
let dog = a as! Dog
print(dog.bark())
}
barkIfDog(Dog(name: "Rex"))مقارنة as? وas!
يُعد as? آمنًا ويُرجع قيمة اختيارية، بينما يُجري as! تحويلًا قسريًا ويتسبب في انهيار البرنامج عند الفشل. اختر بينهما بناءً على مدى يقينك.
class Animal {
let name: String
init(name: String) { self.name = name }
}
class Dog: Animal {
func bark() -> String { return name + " says Woof" }
}
class Cat: Animal {
func meow() -> String { return name + " says Meow" }
}
let a: Animal = Dog(name: "Rex")
let safe = a as? Dog
let forced = a as! Dog
print(safe?.bark() ?? "nil")
print(forced.bark())التحويل القسري للمجموعات
تعمل التحويلات القسرية أيضًا على المجموعات بأكملها، مثل array as! [Dog]، لكن خطر الانهيار نفسه ينطبق على كل عنصر.
class Animal {
let name: String
init(name: String) { self.name = name }
}
class Dog: Animal {
func bark() -> String { return name + " says Woof" }
}
class Cat: Animal {
func meow() -> String { return name + " says Meow" }
}
let animals: [Animal] = [Dog(name: "Rex"), Dog(name: "Buddy")]
let dogs = animals as! [Dog]
for d in dogs { print(d.bark()) }نمط خطير
يتسبب التحويل القسري لمصفوفة تحتوي على عنصر من النوع الخاطئ في انهيار البرنامج. لذلك ينبغي أن تستخدم المجموعات المختلطة as? لكل عنصر.
class Animal {
let name: String
init(name: String) { self.name = name }
}
class Dog: Animal {
func bark() -> String { return name + " says Woof" }
}
class Cat: Animal {
func meow() -> String { return name + " says Meow" }
}
let animals: [Animal] = [Dog(name: "Rex"), Cat(name: "Mia")]
// let dogs = animals as! [Dog] // would crash on the Cat
for a in animals {
if let d = a as? Dog { print(d.bark()) }
}فك التغليف القسري مقابل التحويل القسري
يشبه الرمز ! في as! من الناحية المفاهيمية فك تغليف قيمة اختيارية قسرًا: فهو مريح لكنه خطير إذا كان الافتراض خاطئًا.
class Animal {
let name: String
init(name: String) { self.name = name }
}
class Dog: Animal {
func bark() -> String { return name + " says Woof" }
}
class Cat: Animal {
func meow() -> String { return name + " says Meow" }
}
let a: Animal = Dog(name: "Rex")
let viaOptional = (a as? Dog)!
let viaForce = a as! Dog
print(viaOptional.name, viaForce.name)أفضل ممارسة
اجعل as? خيارك الافتراضي. واحتفظ بـas! للحالات التي يعني فيها الفشل وجود خطأ برمجي تريد إظهاره فورًا أثناء التطوير.
class Animal {
let name: String
init(name: String) { self.name = name }
}
class Dog: Animal {
func bark() -> String { return name + " says Woof" }
}
class Cat: Animal {
func meow() -> String { return name + " says Meow" }
}
func process(_ a: Animal) -> String {
if let d = a as? Dog { return d.bark() }
return "not a dog"
}
print(process(Dog(name: "Rex")))
print(process(Cat(name: "Mia")))مثال ملخص على التحويل القسري
عندما يكون النوع متحققًا منه، تكون قراءة as! واضحة. وعند الشك، يكون التحويل الشرطي الآمن هو الأداة المناسبة.
class Animal {
let name: String
init(name: String) { self.name = name }
}
class Dog: Animal {
func bark() -> String { return name + " says Woof" }
}
class Cat: Animal {
func meow() -> String { return name + " says Meow" }
}
let known: Animal = Dog(name: "Rex")
if known is Dog {
print((known as! Dog).bark())
}اختبار سريع
حلّل خطورة التحويل القسري.
مراجعة: التحويل القسري ومخاطره
لقد تعلمت أن as! يُجري تحويلًا تنازليًا ويفك التغليف إلى نوع غير اختياري، لكنه يتسبب في انهيار البرنامج عند الفشل، وأنه لا ينبغي استخدامه إلا عندما يكون النوع مؤكدًا، غالبًا بعد التحقق باستخدام is، وأن as? يظل الخيار الافتراضي الأكثر أمانًا.
class Animal {
let name: String
init(name: String) { self.name = name }
}
class Dog: Animal {
func bark() -> String { return name + " says Woof" }
}
class Cat: Animal {
func meow() -> String { return name + " says Meow" }
}
let a: Animal = Dog(name: "Rex")
if a is Dog { print((a as! Dog).bark()) } else { print("safe skip") }الأسئلة الشائعة
هل درس «التحويل الإجباري باستخدام as! ومخاطره» مجاني؟
نعم — نص درس «التحويل الإجباري باستخدام as! ومخاطره» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Swift Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Swift Academy 4 دروس في المجموع.
ماذا ستتعلم في «التحويل الإجباري باستخدام as! ومخاطره»؟
استخدم as! فقط عندما يكون نجاح التحويل مضمونًا. تتمرن على Swift Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ Swift Academy؟
لا تُشترط خبرة سابقة. Swift Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 3 من أصل 4.
كم من الوقت يستغرق درس «التحويل الإجباري باستخدام as! ومخاطره»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس Swift Academy هذا؟
نعم. كل درس في Swift Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- أساسيات التحويل إلى النوع الأب والتحويل إلى النوع الابن
- التحويل الشرطي باستخدام as?
- التحويل الإجباري باستخدام as! ومخاطره
- التحقق من الأنواع باستخدام is