أساسيات التحويل إلى النوع الأب والتحويل إلى النوع الابن
انتقل بين أنواع الفئة الأب والفئة الابن.
أساسيات التحويل إلى النوع الأب والتحويل إلى النوع الابن درس مجاني في Swift Academy على CoddyKit. هذا هو الدرس 1 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Swift Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Swift Academy 4 دروس في المجموع.
نظرة عامة على تحويل النوع
يتيح لك تحويل النوع التعامل مع مثيل على أنه من نوع مختلف ضمن تسلسل أنواع الأصناف. وهو فحص للنوع الساكن أو تغييره، وليس تحويلًا للبيانات.
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 d = Dog(name: "Rex")
print(d.bark())تسلسل هرمي للأصناف
يتطلب تحويل النوع وجود تسلسل هرمي. هنا يرث كل من Dog وCat من Animal. ويُعد Dog من نوع Animal.
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 pet: Animal = Dog(name: "Rex")
print(pet.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" }
}
let dog = Dog(name: "Rex")
let asAnimal = dog as Animal
print(asAnimal.name)لماذا نستخدم التحويل التصاعدي
يفيد التحويل التصاعدي في تخزين أصناف فرعية مختلفة معًا، مثل وضعها في مصفوفة واحدة نوعها هو الصنف الأب المشترك.
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 zoo: [Animal] = [Dog(name: "Rex"), Cat(name: "Mia")]
for a in zoo { print(a.name) }التحويل التصاعدي آمن دائمًا
بما أن كل مثيل لصنف فرعي يُعد أيضًا مثيلًا صالحًا للصنف الأب، يقبل المترجم استخدام 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 cat = Cat(name: "Mia")
let animal = cat as Animal
print("Treated as Animal:", animal.name)فقدان الوصول بعد التحويل التصاعدي
بعد تخزين المثيل على أنه من نوع الصنف الأب، لا يمكنك استدعاء سوى أعضاء الصنف الأب. ويظل العضو الخاص بـ Dog، وهو bark()، مخفيًا حتى تُجري تحويلًا تنازليًا.
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")
print(a.name)
// a.bark() would not compile hereمقدمة إلى التحويل التنازلي
يسير التحويل التنازلي في الاتجاه المعاكس: إذ يعامل مرجعًا إلى الصنف الأب على أنه من صنف فرعي محدد لاستعادة أعضائه. وقد يفشل هذا التحويل، لذلك يحتاج إلى 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")
if let dog = a as? Dog {
print(dog.bark())
}لماذا قد يفشل التحويل التنازلي
لا يستطيع المترجم ضمان أن Animal المعين هو فعلًا من نوع Dog. فقد يكون من نوع Cat. لذلك يجب التحقق من التحويلات التنازلية.
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 = Cat(name: "Mia")
let maybeDog = a as? Dog
print("Is it a Dog?", maybeDog != nil)التحويل التنازلي داخل حلقة
من الأنماط الشائعة تكرار عناصر مصفوفة من نوع الصنف الأب وتحويل كل عنصر تحويلًا تنازليًا للتعامل مع الأصناف الفرعية بشكل مختلف.
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 zoo: [Animal] = [Dog(name: "Rex"), Cat(name: "Mia")]
for a in zoo {
if let dog = a as? Dog { print(dog.bark()) }
if let cat = a as? Cat { print(cat.meow()) }
}ملخص التحويل التصاعدي والتنازلي
ينقل التحويل التصاعدي (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 d = Dog(name: "Rex")
let up = d as Animal
let down = up as? Dog
print(up.name, down?.bark() ?? "no")يقتصر تحويل النوع على التسلسل الهرمي
لا يمكنك إجراء تحويل للنوع إلا بين أنواع مرتبطة ضمن التسلسل الهرمي نفسه. ولا يمكن تحويل الأنواع غير المرتبطة إلى بعضها.
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")
print(a is Animal)
print(a is Dog)اختبار سريع
تذكّر اتجاه التحويل الذي ينجح دائمًا.
مراجعة: التحويل التصاعدي والتنازلي
لقد تعلمت أن تحويل النوع يعمل ضمن تسلسل هرمي للأصناف، وأن التحويل التصاعدي باستخدام 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 pets: [Animal] = [Dog(name: "Rex"), Cat(name: "Mia")]
for p in pets {
if let d = p as? Dog { print(d.bark()) } else { print(p.name) }
}الأسئلة الشائعة
هل درس «أساسيات التحويل إلى النوع الأب والتحويل إلى النوع الابن» مجاني؟
نعم — نص درس «أساسيات التحويل إلى النوع الأب والتحويل إلى النوع الابن» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Swift Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Swift Academy 4 دروس في المجموع.
ماذا ستتعلم في «أساسيات التحويل إلى النوع الأب والتحويل إلى النوع الابن»؟
انتقل بين أنواع الفئة الأب والفئة الابن. تتمرن على Swift Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ Swift Academy؟
لا تُشترط خبرة سابقة. Swift Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 1 من أصل 4.
كم من الوقت يستغرق درس «أساسيات التحويل إلى النوع الأب والتحويل إلى النوع الابن»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس Swift Academy هذا؟
نعم. كل درس في Swift Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- أساسيات التحويل إلى النوع الأب والتحويل إلى النوع الابن
- التحويل الشرطي باستخدام as?
- التحويل الإجباري باستخدام as! ومخاطره
- التحقق من الأنواع باستخدام is