在本教程中,我们将讨论 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 中不是关键字。在 Kotlin 中,默认情况下,类是final的。因此,相当于上述 Java 定义的 Kotlin 类看起来像这样:
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的年龄是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)
在上述代码中,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