في هذا الدرس، سنتناول مفاهيم برمجة الكائنات في لغة Kotlin. سنناقش تفصيليًا فصول Kotlin. سنلقي نظرة أيضًا على بناة Kotlin، ووسائط الوصول، والفصول المجردة.
فصل Kotlin
الفصل هو نموذج محدد يجمع بين الوظائف والخصائص. يتم تعريف الفصول في Kotlin باستخدام كلمة الرئيسية
class
تتبعها اسم الفصل. يتم وضع الجسم داخل الأقواس المنحنية.
class FirstClass {
}
يتم إنشاء مثيل من الفصل بالطريقة التالية:
val firstClass = FirstClass()
var new = FirstClass() //here new is the name of the var.
على عكس Java، new
ليست كلمة رئيسية في Kotlin. الفصول بشكل افتراضي هي final في Kotlin. لذلك، يبدو ما يعادل النهج أعلاه في Java كما يلي:
public final class FirstClass {
}
وبالتالي، بشكل افتراضي، الفصول في Kotlin غير قابلة للتوريث. لجعل الفصل غير نهائي، نحتاج إلى إضافة كلمة الرئيسية open
.
open class Me{
}
تسمح تعليقة open
للآخرين بالتورث من هذا الفصل.
مثال على فصل Kotlin
دعونا ننشئ فئة تحتوي على عدد قليل من الوظائف وخاصية. سنرى كيفية الوصول إلى الوظائف والخصائص في تلك الفئة. علاوة على ذلك، سنرى كيفية تعيين خصائص الأعضاء.
class User {
var loggedIn: Boolean = false
val cantChangeValue = "Hi"
fun logOn() {
loggedIn = true
}
fun logOff() {
loggedIn = false
}
}
fun main(args: Array<String>) {
val user = User()
println(user.loggedIn) //false
user.logOn()
println(user.loggedIn) //true
user.logOff()
println(user.loggedIn) //false
user.cantChangeValue = "Hey" //won't compile. Can't modify a final variable.
}
الدالة main
تنتمي إلى فئة Test.kt
. للوصول إلى الأعضاء والوظائف، نحتاج إلى استخدام مشغل النقطة. لا يمكن تعيين خاصية val
مرة أخرى باستخدام مشغل النقطة.
كوتلن init
يتم تعريف كتلة init لكوتلن كما هو موضح أدناه.
class User {
init{
print("Class instance is initialised.")
}
var loggedIn: Boolean = false
val cantChangeValue = "Hi"
fun logOn() {
loggedIn = true
}
fun logOff() {
loggedIn = false
}
}
يتم تنفيذ الكود داخل كتلة init
أولاً عند تم تثبيت الفئة. يتم تشغيل كتلة init
في كل مرة يتم فيها تثبيت الفئة، بأي نوع من بنّاء الكائن كما سنرى فيما بعد. يمكن كتابة عدة كتل مبدئية في فئة. سيتم تنفيذها تسلسليًا كما هو موضح أدناه.
class MultiInit(name: String) {
init {
println("First initializer block that prints ${name}")
}
init {
println("Second initializer block that prints ${name.length}")
}
}
fun main(args: Array) {
var multiInit = MultiInit("Kotlin")
}
//يتم طباعة ما يلي في وحدة التحكم في السجل.
//الكتلة المبدئية الأولى التي تطبع كوتلن
//الكتلة المبدئية الثانية التي تطبع 6
تسمح فئات كوتلن بطباعة الخصائص في التعريف نفسه باستخدام وظيفة also
كما هو موضح أدناه.
class MultiInit(name: String) {
val firstProperty = "First property: $name".also(::println)
init {
println("First initializer block that prints ${name}")
}
val secondProperty = "Second property: ${name.length}".also(::println)
init {
println("Second initializer block that prints ${name.length}")
}
}
fun main(args: Array) {
var multiInit = MultiInit("Kotlin")
}
//يتم طباعة ما يلي.
//الخاصية الأولى: كوتلن
//الكتلة المبدئية الأولى التي تطبع كوتلن
//الخاصية الثانية: 6
//الكتلة المبدئية الثانية التي تطبع 6
بناء Kotlin
بناء Kotlin هي وظائف أعضاء خاصة تستخدم لتهيئة الخصائص. تختلف بناء Kotlin في الكتابة والهيكل عن Java. بشكل افتراضي، يحتوي الفصل على بناء فارغ كما هو موضح أدناه:
class Student {
var name: String
val age : Int
init {
name = "Anupam"
age = 24
}
init {
name = "Anupam Chugh"
//العمر = 26
}
}
fun main(args: Array) {
val student = Student()
println("${student.name} age is ${student.age}")
student.name = "Your"
//student.age = 26 // لن يتم ترجمته. العمر هو val
println("${student.name} age is ${student.age}")
}
//الناتج على الشاشة هو:
//أنوبام تشوغ العمر هو 24
//عمرك هو 24
البناء الأساسي
البناء الأساسي في Kotlin يتم تعريفه في رأس الفصل نفسه كما هو موضح أدناه.
class User(var name: String, var isAdmin: Boolean) {
init {
name = name + " @ JournalDev.com"
println("Author Name is $name. Is Admin? $isAdmin")
}
}
تعريف البناء الأساسي يأتي داخل رأس الفصل. قمنا بتعريف أنواع الخصائص (val/var) في البناء نفسه. ملاحظة: مالم يُحدد على أنها var
، فبشكل افتراضي، تُعتبر مُعطيات البناء val
.
class User(name: String, isAdmin: Boolean)
في الكود أعلاه، لا يمكن إعادة تعيين كل من الاسم و isAdmin. بديلاً، يمكننا أيضًا تعيين مُعطيات البناء إلى الخصائص الأعضاء في الفصل كما هو موضح أدناه.
class User(name: String, val isAdmin: Boolean) {
var username = name
val _isAdmin = isAdmin
init {
username= username + " @ JournalDev.com"
println("Author Name is $name. Is Admin? $_isAdmin")
}
}
fun main(args: Array) {
var user = User("Anupam",false)
user.isAdmin = true //won't compile since isAdmin is val
user._isAdmin = true //won't compile. Same reason.
user = User("Pankaj",true)
}
//الناتج في وحدة تسجيل السجلات:
//اسم المؤلف هو أنوبام. هل هو مسؤول؟ خطأ
//اسم المؤلف هو بانكاج. هل هو مسؤول؟ صحيح
قيم البناء الافتراضية في Kotlin
تسمح Kotlin لنا بتحديد قيم افتراضية في البناء نفسه كما هو موضح أدناه.
class User(name: String, var website: String = "JournalDev") {
init {
println("Author $name writes at $website")
}
init {
website = website + ".com"
println("Author $name writes at $website")
}
}
fun main(args: Array) {
var user = User("Anupam","JournalDev")
user = User("Pankaj","JournalDev")
}
// يتم طباعة ما يلي على وحدة التحكم:
// يكتب المؤلف أنوبام على JournalDev
// يكتب المؤلف أنوبام على JournalDev.com
// يكتب المؤلف بانكاج على JournalDev
// يكتب المؤلف بانكاج على JournalDev.com
البناء الثانوي
يتم كتابة البناء الثانوي داخل جسم الفئة من خلال بادئة بكلمة المفتاح constructor
. يوضح المثال التالي نفس الشيء.
class Student {
var name: String
val age : Int
constructor(name: String, age: Int)
{
this.name = name
this.age = age
}
fun printDetails()
{
println("Name is $name and Age is $age")
}
}
fun main(args: Array) {
var student = Student("Anupam", 24)
student.printDetails()
}
// يتم طباعة ما يلي في وحدة التحكم:
// الاسم هو أنوبام والعمر هو 24
الاستخدام الأكثر شيوعاً للبناء الثانوي يأتي في الفئات الفرعية عندما تحتاج إلى تهيئة الفئة بطرق مختلفة. إذا كانت الفئة تحتوي على بناء أساسي، يجب أن يشير البناء الثانوي إليه في إعلانه. يتم الإعلان عن ذلك باستخدام الكلمة الأساسية this
.
class Student(var name: String, val age: Int) {
var skill: String
init {
skill = "NA"
}
constructor(name: String, age: Int, skill: String) : this(name, age) {
this.skill = skill
}
fun printDetails() {
if (skill.equals("NA"))
println("Name is $name and Age is $age")
else
println("Name is $name and Age is $age Skill is $skill")
}
}
// يتم طباعة ما يلي في وحدة تحكم السجل:
// الاسم هو أنوبام والعمر هو 24
// الاسم هو أنوبام والعمر هو 24 Skill is Kotlin
init
تُستخدم لتهيئة خاصية العضو skill
. يستخدم المُنشئ الثانوي : this
للوكيل إلى المُنشئ الأساسي.
بدلالة واستخدام مُنشئات مُخصصة
حتى الآن، قمنا بالوصول إلى الخصائص وتعديلها في الصف باستخدام عامل النقطة على نموذج الصنف. دعنا نستخدم صياغة set
و get
لنرى كيف يمكننا تخصيص عملية الوصول.
class Name{
var post: String = "default"
set(value) {if(!post.isNotEmpty()) {
throw IllegalArgumentException(" Enter a valid name")
}
field = value
print(value)
}
}
fun main(args: Array<String>) {
var name = Name()
name.post = "Kotlin Classes"
name.post = ""
name.post = "Kotlin Data Classes Our Next Tutorial"
}
سيتم طباعة ما يلي في واجهة تحكم السجل:
Kotlin Classes
Exception in thread "main" java.lang.IllegalArgumentException: Enter a valid name
at Name.setPost(Test.kt:16)
at TestKt.main(Test.kt:78)
متغير field
في المُعين يحفظ القيمة السابقة. لنضيف مُجرى استرداد.
class Name{
var post: String = "default"
set(value) {if(!post.isNotEmpty()) {
throw IllegalArgumentException(" Enter a valid name")
}
field = value
}
get() {
return field.capitalize()
}
}
fun main(args: Array) {
var name = Name()
name.post = "kotlin classes"
println(name.post)
name.post = "kotlin data Classes our next Tutorial"
println(name.post)
}
//سيتم طباعة ما يلي:
//صفوف Kotlin
//صنفات البيانات في Kotlin القادمة في البرنامج التعليمي التالي
capitalize()
يقوم بتهيئة الحرف الأول من السلسلة بأحرف كبيرة. ملاحظة: إذا كانت الخاصية هي val
، فإن طريقة set
لن تُترجم.
مُعدلات رؤية Kotlin
- عام: أي صنف، وظيفة، خاصية، واجهة، أو كائن لديه هذا المُعدل الظاهر ويمكن الوصول إليه من أي مكان.
- خاص: تعريف الفئة/الوظيفة بهذا المعدل يمكن الوصول إليه فقط داخل نفس الملف. يمكن الوصول إلى عضو/خاصية في فئة/وظيفة بهذا المعدل فقط داخل تلك الكتلة.
- محمي: هذا المعدل مماثل للخاص، باستثناء أنه يسمح بالرؤية والوصول داخل الفئات الفرعية.
- داخلي: يمكن الوصول إلى الفئة/الواجهة/الوظيفة بهذا المعدل فقط داخل نفس الوحدة.
يمكن تطبيق معدلات الرؤية على المُباني أيضًا. يتطلب تعيين معدل للمُبني الأساسي مناطقنا تحديد الكلمة الرئيسية constructor
إلى جانب المُبني في رأس الفئة.
class Student private constructor (var name: String, val age: Int) {
var skill: String
init {
skill = "NA"
}
constructor(name: String, age: Int, skill: String) : this(name, age) {
this.skill = skill
}
fun printDetails() {
if (skill.equals("NA"))
println("Name is $name and Age is $age")
else
println("Name is $name and Age is $age Skill is $skill")
}
}
fun main(args: Array) {
var student = Student("Anupam",24,"Kotlin")
student.printDetails()
}
//prints
//الاسم هو أنوبام والعمر 24 المهارة هي Kotlin
لا يمكن استدعاء المُبنيات الخاصة خارج الفئة. في الشفرة أعلاه، يمكننا تحديد فئة في وظيفة مختلفة فقط باستخدام المُنشئ الثانوي.
فئة كوتلن المجردة
مثل جافا، يُستخدم الكلمة الرئيسية abstract
لتعريف الفئات المجردة في كوتلن. لا يمكن تحديد فئة مجردة. ومع ذلك، يمكن أن يتمورث منها الفئات الفرعية. بشكل افتراضي، فإن أعضاء الفئة المجردة غير المجردة ما لم يُحدد خلاف ذلك.
abstract class Person(name: String) {
init {
println("Abstract Class. init block. Person name is $name")
}
abstract fun displayAge()
}
class Teacher(name: String): Person(name) {
var age : Int
init {
age = 24
}
override fun displayAge() {
println("Non-abstract class displayAge function overridden. Age is $age")
}
}
fun main(args: Array) {
val person = Teacher("Anupam")
person.displayAge()
}
//يتم طباعة ما يلي في وحدة التحكم.
//فئة مجردة. كتلة init. اسم الشخص هو أنوبام
//فئة غير مجردة. العمر 24
ملحوظة: تعتبر الفئات المجردة افتراضيًا open
. لذا، ليس مطلوبًا إضافة معيار مفتوح للسماح بالتمديد. يُستخدم كلمة override
لتجاوز طريقة في الفئة الفرعية. لقد تناولنا أساسيات فئات Kotlin في هذا البرنامج التعليمي. لا تزال هناك الكثير من المواضيع مثل فئات البيانات، والفئات المختومة، والتوريث، إلخ. سنقوم بتغطيتها في البرامج التعليمية القادمة. المراجع: مستندات Kotlin
Source:
https://www.digitalocean.com/community/tutorials/kotlin-class-constructor