Kotlin学习笔记——类和对象
2017-09-19 15:00
204 查看
跟Java一样,Kotlin里面类的声明使用的是关键字class,类的声明包含有三部分:类名,类头,类体,其中,类头和类体是可选的。
Constructors
在Kotlin中,一个类有一个primary constructor,一个或多个secondary constructors。primary constructor 属于类头部分,它在类名之后。
2
如果primary constructor没有任何注解或者指示符,constructor关键字可以被省略。
2
相反,如果primary constructory有注解或者可见的指示符,constructor是必须的。
primary constructor不能包含任何的代码,初始代码可以放在初始块中,初始化代码块以init关键字开头。
2
3
4
5
6
需要注意的是,在主构造函数里,可以直接用这些参数变量赋值给类的属性,或者用构造代码块来实现初始化。
2
3
4
5
6
7
8
9
10
11
也可以直接把primary constructor中的参数直接声明成为类的属性,定义的方法是在参数名前加上 var 或者 val 关键字,val 是代表属性是常量。在创建类的时候,调用构造函数就直接把它们进行了初始化,这样就不用在类中单独声明类的属性了。
2
3
4
Secondary Constructors
除了primary constructory,还有secondary constructors,同样也是constructor开头,位于类体中。
值得说明的是,如果primary constructory和secondary constructors同时存在,每个secondary constructor需要委托到primary constructor中去,或者间接通过另一个secondary constructors来委托。使用方法就是使用this,表示委托到本类的另一个构造函数中。
2
3
4
5
如果非抽象的类没有声明任何的构造函数,它默认继承一个没有任何参数的公有构造器,这个跟Java中的默认构造器类似。如果希望它继承的是一个私有的构造器,就需要显示的指明。
2
创建类实例
跟Java类似,只是没有new关键字。
2
3
类成员
1、构造器和初始化块
2、成员函数
3、属性
4、内部类
5、对象声明
继承
在Kotlin中所以的类都有一个默认的父类Any,这个类似于Java中的Object。
显示的定义一个父类
2
3
open关键字跟Java中的final是恰恰相反的。
从上面看到,如果父类有primary constructor,子类必须在继承的时候以primary constructor的形式继承。
如果父类没有primary constructor,子类的每个secondary constructor在右边使用super来对它进行初始化。
2
3
4
5
6
7
重写成员函数
对于可以重写的函数,都需要显示的指明,使用的是open关键字。如果没有,在子类中声明跟父类相同的方法是非法的。
2
3
4
5
6
7
在子类中,如果是重新父类的函数也需要使用override关键字显示的指明。
在子类中被标记为override的成员函数本身也是可以被重新的,也就是open的,如果希望它禁止被重写,需要使用final关键字。
2
3
重写规则
如果一个类继承自多个类,并且它的这些父类都有同一个可以重写的函数,那么这个类必须重写这个函数并且提供它自己的实现,另外在子类中指示父类的方法是
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
上面类A和B都有f()函数可以重写,所以C类,必须重写这个函数f(),主要是为了消除歧义。
抽象类
跟Java一样,使用abstract关键字。
2
3
4
5
6
7
8
Companion Objects
Kotlin 移除了 static 的概念。通常用 companion object 来实现类似功能。
你可能时常会看到一个 Activity 有一个 静态类型的 string,名叫TAG,和一个启动 Activity 的静态方法。Java 中的实现如下:
2
3
4
5
6
7
在 Kotlin 下的实现如下:
2
3
4
5
6
7
8
9
10
11
12
13
Sealed Classe
它类似于一个扩展的enum类,不同的是枚举的实例是唯一的,而密封类可以有很多实例,它们可以有不同的状态。它使用的关键字是sealed。
2
3
4
5
我们可以使用when表达式匹配所有选项而不使用else分支:
2
3
4
5
6
参考文章:Classes and Inheritance
class Empty1
Constructors
在Kotlin中,一个类有一个primary constructor,一个或多个secondary constructors。primary constructor 属于类头部分,它在类名之后。
class Person constructor(firstName: String) { }1
2
如果primary constructor没有任何注解或者指示符,constructor关键字可以被省略。
class Person(firstName: String) { }1
2
相反,如果primary constructory有注解或者可见的指示符,constructor是必须的。
class Customer public @Inject constructor(name: String) { ... }1
primary constructor不能包含任何的代码,初始代码可以放在初始块中,初始化代码块以init关键字开头。
class Customer(name: String) { init { logger.info("Customer initialized with value ${name}") } }1
2
3
4
5
6
需要注意的是,在主构造函数里,可以直接用这些参数变量赋值给类的属性,或者用构造代码块来实现初始化。
class Customer(firstName: String, lastName: String, email: String) { var firstName: String var lastName: String var email: String init { this.firstName = firstName this.lastName = lastName this.email = email } }1
2
3
4
5
6
7
8
9
10
11
也可以直接把primary constructor中的参数直接声明成为类的属性,定义的方法是在参数名前加上 var 或者 val 关键字,val 是代表属性是常量。在创建类的时候,调用构造函数就直接把它们进行了初始化,这样就不用在类中单独声明类的属性了。
class Customer( var firstName: String, var lastName: String, var email: String)1
2
3
4
Secondary Constructors
除了primary constructory,还有secondary constructors,同样也是constructor开头,位于类体中。
值得说明的是,如果primary constructory和secondary constructors同时存在,每个secondary constructor需要委托到primary constructor中去,或者间接通过另一个secondary constructors来委托。使用方法就是使用this,表示委托到本类的另一个构造函数中。
class Person(val name: String) { constructor(name: String, parent: Person) : this(name) { parent.children.add(this) } }1
2
3
4
5
如果非抽象的类没有声明任何的构造函数,它默认继承一个没有任何参数的公有构造器,这个跟Java中的默认构造器类似。如果希望它继承的是一个私有的构造器,就需要显示的指明。
class DontCreateMe private constructor () { }1
2
创建类实例
跟Java类似,只是没有new关键字。
val invoice = Invoice() val customer = Customer("Joe Smith")1
2
3
类成员
1、构造器和初始化块
2、成员函数
3、属性
4、内部类
5、对象声明
继承
在Kotlin中所以的类都有一个默认的父类Any,这个类似于Java中的Object。
class Example // Implicitly inherits from Any1
显示的定义一个父类
open class Base(p: Int) class Derived(p: Int) : Base(p)1
2
3
open关键字跟Java中的final是恰恰相反的。
从上面看到,如果父类有primary constructor,子类必须在继承的时候以primary constructor的形式继承。
如果父类没有primary constructor,子类的每个secondary constructor在右边使用super来对它进行初始化。
class MyView : View { constructor(ctx: Context) : super(ctx) { } constructor(ctx: Context, attrs: AttributeSet) : super(ctx, attrs) { } }1
2
3
4
5
6
7
重写成员函数
对于可以重写的函数,都需要显示的指明,使用的是open关键字。如果没有,在子类中声明跟父类相同的方法是非法的。
open class Base { open fun v() {} fun nv() {} } class Derived() : Base() { override fun v() {} }1
2
3
4
5
6
7
在子类中,如果是重新父类的函数也需要使用override关键字显示的指明。
在子类中被标记为override的成员函数本身也是可以被重新的,也就是open的,如果希望它禁止被重写,需要使用final关键字。
open class AnotherDerived() : Base() { final override fun v() {} }1
2
3
重写规则
如果一个类继承自多个类,并且它的这些父类都有同一个可以重写的函数,那么这个类必须重写这个函数并且提供它自己的实现,另外在子类中指示父类的方法是
super<A>,A为父类类名,这样就可以指示不同的父类了。
open class A { open fun f() { print("A") } fun a() { print("a") } } interface B { fun f() { print("B") } // interface members are 'open' by default fun b() { print("b") } } class C() : A(), B { // The compiler requires f() to be overridden: override fun f() { super<A>.f() // call to A.f() super<B>.f() // call to B.f() } }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
上面类A和B都有f()函数可以重写,所以C类,必须重写这个函数f(),主要是为了消除歧义。
抽象类
跟Java一样,使用abstract关键字。
open class Base { open fun f() {} } abstract class Derived : Base() { override abstract fun f() }1
2
3
4
5
6
7
8
Companion Objects
Kotlin 移除了 static 的概念。通常用 companion object 来实现类似功能。
你可能时常会看到一个 Activity 有一个 静态类型的 string,名叫TAG,和一个启动 Activity 的静态方法。Java 中的实现如下:
class LaunchActivity extends AppCompatActivity { public static final String TAG = LaunchActivity.class.getName(); public static void start(Context context) { context.startActivity(new Intent(context, LaunchActivity.class)); } }1
2
3
4
5
6
7
在 Kotlin 下的实现如下:
class LaunchActivity { companion object { val TAG: String = LaunchActivity::class.simpleName fun start(context: Context) { context.startActivity(Intent(context, LaunchActivity::class)) } } } Timber.v("Starting activity ${LaunchActivity.TAG}") LaunchActivity.start(context)1
2
3
4
5
6
7
8
9
10
11
12
13
Sealed Classe
它类似于一个扩展的enum类,不同的是枚举的实例是唯一的,而密封类可以有很多实例,它们可以有不同的状态。它使用的关键字是sealed。
sealed class Expr { class Const(val number: Double) : Expr() class Sum(val e1: Expr, val e2: Expr) : Expr() object NotANumber : Expr() }1
2
3
4
5
我们可以使用when表达式匹配所有选项而不使用else分支:
fun eval(expr: Expr): Double = when(expr) { is Const -> expr.number is Sum -> eval(expr.e1) + eval(expr.e2) NotANumber -> Double.NaN // the `else` clause is not required because we've covered all the cases }1
2
3
4
5
6
参考文章:Classes and Inheritance
相关文章推荐
- Hibernate学习笔记(2):对象的三种状态
- Kotlin学习笔记3-3 类和对象-接口
- 《Effective C++》学习笔记条款21 必须返回对象时,别妄想返回其reference
- 类与对象的基本定义——学习笔记(根据李兴华老师《Java8编程开发入门》网课记录)
- 《javascript高级程序设计》学习笔记(四):javascript 的类和对象
- 《悟透javascript》学习笔记:五、奇妙的对象
- kotlin学习笔记——Kotlin Android Extensions
- 《JavaScript权威指南》学习笔记 第五天 window对象的方法。
- 《Spring技术内幕》学习笔记8——创建AOP代理对象并对目标对象切面拦截
- Kotlin------类和对象(一)
- 《Java编程思想》学习笔记2——对象初始化和面向对象特性 .
- 《java JDK7 学习笔记》之类和对象
- 《Python学习手册》学习笔记(34)之第34章异常对象(关键词:编程语言/Python/异常/异常对象)
- (十三)kotlin对象表达式和对象声明
- 《JavaScript高级程序设计》学习笔记(对象2)
- 《Windows via C/C++》学习笔记 —— 内核对象的“线程同步”之“事件内核对象”
- Kotlin类和对象 (九)--- 嵌套类与内部类
- 《Java面向对象编程》学习笔记1——面向对象开发方法
- kotlin学习笔记——扩展函数(anko)和网络请求
- 《Effective C++》学习笔记条款13 以对象管理资源