English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
في هذا المقال، ستتعلم النّسب. وبشكل أكثر دقة، ما هو النّسب وكيفية تنفيذه في Kotlin باستخدام النّسب (باستخدام أمثلة).
继承是面向对象编程的关键功能之一。它允许用户从现有类(基类)创建一个新类(派生类)。
派生类继承了基类的所有功能,并且可以拥有自己的其他功能。
在详细介绍 Kotlin 继承之前,建议您阅读以下两篇文章:
假设在您的应用程序中需要三个角色-一个数学老师(MathTeacher),一个足球运动员(Footballer)和一个商人(Businessman).
由于所有角色都是人,因此他们可以 走路 和 说话。但是,他们也有一些特殊技能。数学老师可以教数学(teachMath),足球运动员可以踢足球(playFootball),商人可以经营企业(runBusiness).
您可以单独创建三个可以走路,说话和执行其特殊技能的类。
在每个类中,您将为每个角色复制相同的步行和说话代码。
如果要添加新特性 - eat(吃),则需要为每个角色实现相同的代码。这很容易导致出错(复制时)和重复代码。
如果我们有一个具有基本功能的 Person 类,比如说,走,吃,睡,并根据我们的角色为这些功能添加特殊技能,那就容易多了。这是通过继承完成的。
使用继承,现在您不需要为每个类实现相同的 walk()、talk() 和 eat() 代码。你只需要继承它们就行了。
因此,对于 MathTeacher(派生类),您可以继承 Person(基类)的所有功能,并添加一个新功能 teachingMath()。同样,对于 Footballer 类,您继承了 Person 类的所有功能,并添加了新功能 playFootball(),依此类推。
这使您的代码更简洁,可理解且可扩展。
重要的是要记住:在处理继承时,每个派生类都应满足其是否为“基”类的条件。在上面的示例中,MathTeacher 是一个 Person(人),Footballer 是一个 Person(人)。您不能认为“商人(Businessman)就是企业(Business)”。
让我们尝试在代码中实现以上讨论:
open class Person(age: Int) { //吃饭、说话、走路的代码 {} class MathTeacher(age: Int): Person(age) { // خصائص معلم الرياضيات الأخرى {} class Footballer(age: Int): Person(age) { // خصائص لاعب كرة القدم الأخرى {} class Businessman(age: Int): Person(age) { // خصائص المندوب الأخرى {}
في هذا السياق، تكون Person الفئة الأساسية، بينما تكون الفئات MathTeacher، Footballer و Businessman هي الفئات الفرعية المستنسخة من الفئة Person.
لاحظ أن الكلمة المفتوحة open في الفئة الأساسية Person، هذا أمر مهم جدًا.
بالتقدير الافتراضي، تكون الفئات في Kotlin نهائية. إذا كنت مألوفًا بـ Java، فإنك تعرف أن الفئات النهائية لا يمكن توليد فئات فرعية منها. يسمح لك استخدام التعليق @ على الفئة بتمكين محول البرنامج من توليد فئات فرعية منها.
مفتوح فئة Person(age: Int, name: String) { بداية { println("اسمى هو $name.") println("عمرى هو $age") {} {} class MathTeacher(age: Int, name: String): Person(age, name) { fun teachMaths() { println("أدرس في المدرسة الابتدائية.") {} {} class Footballer(age: Int, name: String): Person(age, name) { مهمة playFootball() { println("أخدم فريق لوس أنجلوس غالاكسي.") {} {} fun main(args: Array<String>) { t1 = MathTeacher(25, "Jack") t1.teachMaths() println() val f1 = Footballer(29, "Christiano") f1.playFootball() {}
عند تشغيل هذا البرنامج، الناتج هو:
اسمى هو Jack. عمرى هو 25 أدرس في المدرسة الابتدائية. اسمى هو Cristiano. عمرى هو 29 أخدم فريق لوس أنجلوس غالاكسي.
في هذا السياق، تم استنساخ فئتين MathTeacher و Footballer من الفئة Person.
يحدد بناء الفئة Person الرئيسي اثنين من الخصائص: age و name، ويكون لديه برنامج تعريفي.
الفئات الفرعية MathTeacher و Footballer لها دوال عضوية خاصة بها teachMaths() و playFootball()، هذه الدوال يمكن الوصول إليها فقط من خلال كائنات الفئات الخاصة بها.
عند إنشاء كائن للفئة MathTeacher t1،
t1 = MathTeacher(25, "Jack")
سيتم نقل المعلمات إلى معادلة الرئيسية. عند إنشاء كائن في Kotlin، يتم استدعاء مكتبة البداية. نظرًا لأن MathTeacher هو فرع من فئة Person، فإنه سيبحث في مكتبة البداية للفئة الأساسية (Person) ويقوم بتنفيذها. إذا كان لدي MathTeacher مكتبة بداية، فإن المبرمج سيقوم أيضًا بتنفيذ مكتبة البداية للفئة المشتقة.
ثم، يتم استدعاء دالة teachMaths() باستخدام جملة t1.teachMaths().
عند إنشاء فئة لـ f1، يعمل البرنامج بنفس الطريقة. يقوم بتنفيذ مكتبة الفئة الأساسية. ثم، يتم استدعاء دالة playFootball() في فئة Footballer باستخدام جملة f1.playFootball().
إذا كان لديها معادلة رئيسية، فيجب استخدام معلمات معادلة الرئيسية لتحديث الفئة الأساسية. في البرنامج المذكور أعلاه، لدي كل من الفئتين المشتقة اثنين من المعلمات age و name، وقد تم تفعيلهما في معادلة الرئيسية للفئة الأساسية.
هذا مثال آخر:
مفتوح فئة Person(age: Int, name: String) { // بعض الكود {} فئة Footballer(age: Int, name: String, club: String): Person(age, name) { بداية { println("لاعب كرة القدم ذو العمر $age ويحمل الاسم $name، يلعب مع $club.") {} مهمة playFootball() { println("أنا ألعب كرة القدم.") {} {} fun main(args: Array<String>) { f1 = Footballer(29, "Cristiano", "LA Galaxy") {}
في هذا السياق، معادلة الفئة المشتقة الرئيسية تحتوي على 3 معلمات، بينما تحتوي الفئة الأساسية على 2 معلمات. يرجى ملاحظة أن المعلمتان اللتان للفئة الأساسية قد تمت تفعيلهما بالفعل.
إذا لم يكن هناك معادلة رئيسية، فيجب على كل فئة أساسية تحديث الفئة الأساسية (استخدام كلمة المفتاح super)، أو تفويض إلى معادلة أخرى تقوم بذلك. على سبيل المثال
fun main(args: Array<String>) { p1 = AuthLog("كلمة_سر_سيئة") {} مفتوح فئة Log { بيانات: String = "" عدد_البيانات = 0 المعادلة(_data: String) { {} المعادلة(_data: String, _numberOfData: Int) { data = _data numberOfData = _numberOfData println("$data: $numberOfData times") {} {} class AuthLog: Log { constructor(_data: String): this("From AuthLog -> + $_data", 10) { {} constructor(_data: String, _numberOfData: Int): super(_data, _numberOfData) { {} {}
للإطلاع على مزيد من المعلومات حول كيفية عمل هذا البرنامج، يرجى زيارةبناءً ثانوي Kotlin.
إذا كانت الفئة الأصلية والفئة الفرعية تحتويان على أعضاء (أو خصائص) بنفس الاسم، قد تحتاج إلى استخدام كلمة المفتاح override لتعديل عضو الفئة الفرعية، ولفئة الأصلية استخدام كلمة المفتاح open.
// بناءً رئيسي خالي open class Person() { open fun displayAge(age: Int) { println("ماهو عمري هو $age.") {} {} class Girl: Person() { override fun displayAge(age: Int) { println("عمر افتراضي هو ${age - 5}.") {} {} fun main(args: Array<String>) { val girl = Girl() girl.displayAge(31) {}
عند تشغيل هذا البرنامج، الناتج هو:
ماهو عمري الافتراضي هو 26.
في هذا السياق، يتم دعوة girl.displayAge(31) لأسلوب displayAge() في الفئة الفرعية Girl.
يمكنك تغطية خصائص الفئة الأصلية بنفس الطريقة.
يمكنك زيارة المستلمون والمزودون في Kotlin للإطلاع على كيفية عمله، يرجى زيارة
// بناءً رئيسي خالي open class Person() { open var age: Int = 0 get() = field set(value) { field = value {} {} class Girl: Person() { override var age: Int = 0 get() = field set(value) { field = value - 5 {} {} fun main(args: Array<String>) { val girl = Girl() girl.age = 31 println("ماهو عمري الافتراضي هو ${girl.age}.") {}
عند تشغيل هذا البرنامج، الناتج هو:
عمر افتراضي هو 26.
كما ترون، لقد استخدمنا كلمات المفتاح override وopen لـ age الخاصية في الفئة الفرعية والفئة الأصلية على التوالي.
يمكنك استخدام كلمة المفتاح super لندعو الدالة من الفئة الفرعية (ووصول إلى الخصائص). كيف يتم القيام بذلك:
open class Person() { open fun displayAge(age: Int) { println("ماهو عمري الفعلي هو $age.") {} {} class Girl: Person() { override fun displayAge(age: Int) { //إتصال بالوظيفة في الصفحة الأصلية super.displayAge(age) println("عمر افتراضي هو ${age - 5}.") {} {} fun main(args: Array<String>) { val girl = Girl() girl.displayAge(31) {}
عند تشغيل هذا البرنامج، الناتج هو:
عمر حقيقي هو 31. عمر افتراضي هو 26.