面向对象对象编程:类,接口,继承,嵌套,以及独有的数据类和封装
面向对象是软件的开发方法,也是计算机界应用很广的一种编程范式,它将数据和方法看成一个整体来看待, 将其抽象成一个具体的模型。
虽然Kotlin和Java,在面向对象上面的一些概念上面有一点差异,但底层的思想是没有变的。
类
//定义了一个Person类, Person有两个属性分别是name, age
class Person(val name: String, var age: Int)
这段代码在Java中是这样写的:
public class Person {
private String name;//不可以修改
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age
}
public void setAge(int age) {
this.age = age;
}
}
Person类的name是用val修饰的,初始化没有将无法修改,这个逻辑对应到Java中,就是该变量只有getter没有setter。
kotlin定义的类,在默认情况下是public,编译器会帮助我们生成构造函数,对于类中的属性,编译器也会根据实际情况,自动生成getter和setter。
自定义属性getter
我们来看前面的例子:
如果我们希望它增加一个功能,叫做isAdult(),希望根据年龄的大小自动判断是不是成年人,也就是age > 18。
class Person(val name: String, var age Int) {
//写的清爽一点
fun isAdult() = age >= 18
}
我们可以将isAdult定义成Peson的属性,
class Person(val name: String, var age: Int) {
val isAdult
get() = age >= 18//这就是isAdult属性的getter方法
}
所谓的getter就是获取属性值的方法,我们通过自定义这个get()方法,就可以改变返回值的规则。
比如这里的年龄大于18,就是成年人,这个规则就是通过自定义来实现的。
以上的isAdult,我们没有写它的类型,因为编译器会自动推导它的类型是Boolean类型,因为只有一行,我们直接使用等号进行连接。
如果get()方法内部比较复杂,我们仍然可以向正常函数那样,带上花括号
class Person(val name: String, var age: Int) {
val isAdult: Boolean
get() {
return age >= 18
}
}
这种情况下,编译器的自动类型推导就失效了,所以我们要为isAdult属性增加明确的类型Booean
但是你不可以将代码写成这样
class Person(val name: String, var age: Int) {
val isAdult = age >= 18//这样写编译会出错
}
自定义属性setter
现在我们需要另一个需求,希望在age被修改的时候,能够做一些日志统计工作,如果我们直接在setAge()方法当中加入一些逻辑就可以了。
在kotlin中,可以使用setter这个方法。
class Person{
var age: Int = 0
set(value: Int) {
log(value)
field = value//这里的field指代的就是value,field是个关键字
}
}
所谓setter就是可以对属性赋值的方法
抽象类与继承
抽象类,不是具体的类,
现在我们将Peson定义一个抽象类
abstract class Person(val name: String) {
abstract fun walk()
}
kotlin中的继承:
除了抽象类以外,正常的类也可以进行继承,不过我们必须对这个类标记为open,如果一个类不是抽象类,并没有使用open修饰的话,它是无法被继承的。
//在kotlin中使用冒号进行表示继承
public class MainActiveity : Activity{
Override fun onCreate() {...}
}
open class Person() {
abstract fun walk()
}
class Boy: Person() {
//...
}
对于,Kotlin的类,默认是不可以进行继承的,open修饰之后可以继承,但是属性和方法不可以进行重写。但是使用open修饰之后就可以重写了。
open class Person{
val canWalk: Boolean = false
fun walk()
}
class Boy : Person{
//报错
override val canWalk: Boolean = true
//报错
override fun walk() {
}
}
接口和实现
interface Behavior {
fun walk()
}
class Person(val name: String): Behavior {
override fun walk() {
//walk
}
}
内部类
class A {
val name: String = ""
//使用内部类的时候要加上inner关键字
inner class B{
println(name)
foo()
}
}
只有我们真正需要访问外部类成员的时候,我们才会加上inner关键字