在本教程中,我們將討論Kotlin的面向對象編程概念。我們將詳細討論Kotlin類。我們還將討論Kotlin的構造函數、訪問修飾符和抽象類。
Kotlin類
類是一個定義藍圖,用於分組函數和屬性。在Kotlin中,使用關鍵字
class
後跟類名來定義類。主體部分放在花括號內。
class FirstClass {
}
可以通過以下方式實例化類:
val firstClass = FirstClass()
var new = FirstClass() //here new is the name of the var.
與Java不同,Kotlin中沒有new
關鍵字。在Kotlin中,類默認是final的。因此,上述Java定義的等價物將如下所示:
public final class FirstClass {
}
因此,默認情況下,Kotlin中的類是不可繼承的。要使類不是final,我們需要添加關鍵字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
屬性。
Kotlin初始化
Kotlin初始化塊的定義如下所示。
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")
}
//以下在日誌控制台中打印。
//第一個初始化塊打印Kotlin
//第二個初始化塊打印6
Kotlin類允許在聲明本身中使用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")
}
//以下將被打印。
//第一個屬性:Kotlin
//第一個初始化塊打印Kotlin
//第二個屬性:6
//第二個初始化塊打印6
Kotlin建構函式
Kotlin建構函式是特殊的成員函式,用於初始化屬性。 Kotlin中的建構函式與Java相比具有不同的寫法和結構。 默認情況下,類具有空建構函式,如下所示:
class Student {
var name: String
val age : Int
init {
name = "Anupam"
age = 24
}
init {
name = "Anupam Chugh"
//age = 26
}
}
fun main(args: Array) {
val student = Student()
println("${student.name} age is ${student.age}")
student.name = "Your"
//student.age = 26 //無法編譯。 age是val
println("${student.name} age is ${student.age}")
}
//以下內容將顯示在控制台上:
//Anupam Chugh age is 24
//Your age is 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)
在上面的代碼中,name和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)
}
//以下內容將在日誌控制台中打印。
//作者名稱是Anupam。 是否為管理員? false
//作者名稱是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")
}
//以下內容會在控制台上輸出:
//作者 Anupam 在 JournalDev 上撰寫
//作者 Anupam 在 JournalDev 上撰寫.com
//作者 Pankaj 在 JournalDev 上撰寫
//作者 Pankaj 在 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()
}
//以下內容會在控制台上輸出:
//姓名為 Anupam,年齡為 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")
}
}
//以下內容會在日誌控制台上輸出:
//姓名為 Anupam,年齡為 24 歲
//姓名為 Anupam,年齡為 24 歲 Skill is Kotlin
init
區塊用於初始化成員屬性skill
。次要建構子使用: this
委派給主要建構子。
自定義 Getter 和 Setter
迄今為止,我們使用類的實例上的點運算符來訪問和修改類中的屬性。讓我們使用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)
在 Setter 中的field
變數保存了舊值。讓我們添加一個 Getter。
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 可見性修飾符
- Public: 具有此修飾符的任何類、函數、屬性、接口或對象都是可見的,可以從任何地方訪問。
- 私有:使用此修飾詞定義的類別/函數僅能在同一檔案中存取。在具有此修飾詞的類別/函數中的成員/屬性僅能在該區塊內存取。
- 保護:此修飾詞與私有相同,唯一的不同是它允許在子類別中可見並存取。
- 內部:具有此修飾詞的類別/介面/函數僅能在同一模組中存取。
可見性修飾詞也適用於建構函數。將修飾詞分配給主要建構函數需要我們在類別標頭中指定關鍵字 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
//名稱是 Anupam 而年齡是 24,技能是 Kotlin
私有建構函數無法在類別外部調用。在上述程式碼中,我們只能使用次要建構函數在不同函數中實例化該類別。
Kotlin 抽象類別
與 Java 類似,abstract
關鍵字用於在 Kotlin 中宣告抽象類別。抽象類別無法被實例化,但可以被子類別繼承。預設情況下,抽象類別的成員是非抽象的,除非另有聲明。
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()
}
//以下內容會被列印在控制台中。
//抽象類別。初始化區塊。人名是 Anupam
//非抽象類別。年齡是 24
注意:抽象類別預設為open
。因此,不需要添加open
修飾符以允許子類別化。override
關鍵字用於覆蓋子類別中的方法。我們在本教程中已經介紹了 Kotlin 類別的基礎知識。還有許多其他內容,例如資料類別、密封類別、繼承等等。我們將在接下來的教程中涵蓋它們。參考資料:Kotlin 文檔
Source:
https://www.digitalocean.com/community/tutorials/kotlin-class-constructor