Kotlin之构造方法

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/cadi2011/article/details/85761863

0、说构造方法前,先贴个例子哦

class Cat {
    private var name: String? = null

    constructor() : super() {}

    constructor(temp: String) {
        this.name = temp           //同样Kotlin这里也隐式的调用了super()
    }
}

等同于java中的

public class Cat {
    private String name = null;

    public Cat(){
        super();
    }

    public Cat(String temp){     //隐式调用了基类Object的无参构造方法
                                //即隐式执行了super()
        this.name = temp;         
    }
}

1、看下官网是如何描述的http://kotlinlang.org/docs/reference/classes.html

A class in Kotlin can have a primary constructor and one or more secondary constructors

在Kotlin的class中可以有一个主构造方法和一个或者多个次要构造方法

 The primary constructor is part of the class header: it goes after the class name

主要的构造方法是class头部的一部分。它跟随在class名字后面。

2、primary constructor 第一种语法

class Person constructor(firstName: String) {
}

3、primary constructor 第二种语法

if the primary constructor does not have any annotations or visibility modifiers, the constructor keyword can be omitted

如果主构造方法没有任何注解修饰或者访问权限的修饰,constructor关键字可以省略掉哦

class Person (firstName: String) {
}

4、不能省略primary constructor的情况之一,看见了吧,私有的constructor

class Cat private constructor() {

}

5、primary constructor的特点就是没有代码块内容,你也发现了吧

The primary constructor cannot contain any code. Initialization code can be placed in initializer blocks, which are prefixed with the init keyword.

在主要构造方法中没有包含任何代码,初始化代码可以用初始化代码块来放置,使用关键字init放在代码块前面

class Cat  (var name : String, var age: Int) {
    init {
        println(name)
        println(age)
    }
}

6、代码的初始化顺序,我就不在这里写了啊,以后在class的初始化顺序中,专门总结吧

7、当我们定义一个类时,我们如果没有为其显式提供Primary Constructor,Kotlin编译器会默认为其生成一个无参主构造,这点和Java是一样的

class Cat() {  //这是显式的写上无参构造方法的情况
    
}
class Cat{   //这时候虽然没写主构造方法,同java中一样,编译器会隐式的加上
    
}

8、如果主构造方法,参数不填写var或者val,会怎么样?看注释吧

class Cat(name:String){
    
    init {
        name = "Katty" #这里是错误的,name没有被var修饰,被认为是val,即常量
    }
}

9、Much the same way as regular properties, the properties declared in the primary constructor can be mutable (var) or read-only (val).

与常规属性一样,主构造方法中声明的参数可以是可变的(var)或只读的,看下例子

class Person(val firstName: String, val lastName: String, var age: Int) { ... }

10、看下一个主构造方法加注解的例子,此时constructor关键字是不可以省略的

class Customer public @Inject constructor(name: String) { ... }

10-1、主构造方法中的参数添加了var或val的好处,加了var或者val的参数,相当于实例变量了,这里有待自己去研究,可能形容不准确,官方也没有说明

难道不加var或者val就不行吗?所以

11、Secondary Constructors 次构造方法,没想到一总结就是这么多

The class can also declare secondary constructors, which are prefixed with constructor:

类里面可以写次构造方法,以constructor为前缀,看下例子

class Person {
    constructor(parent: Person) {
        parent.children.add(this)
    }
}

12、踩坑,次构造方法同普通方法一样,参数是不能加var或者val修饰的

class Cat(val name:String){

    var age : Int = 0

    constructor( name : String, age : Int) : this(name) { #刚才我以为能像主构造方法一样 
                                                         #可以加var或val,结果不行,结果是不行的
        this.age = age
    }
}

13、总之次构造方法一定要调用主构造方法,即使是无参的主构造方法,也会被隐式调用,如果是有参数的主构造方法,就需要你必须显式的使用this进行调用

a、次构造方法必须显示调用有参数的主构造方法

b、或者显示调用其他次构造方法,由其他次构造方法调用主构造方法

c、使用关键字 this

if the class has a primary constructor, each secondary constructor needs to delegate to the primary constructor, either directly or indirectly through another secondary constructor(s). Delegation to another constructor of the same class is done using the this keyword

如果类有一个主构造方法,每个次构造方法都需要直接或间接地通过另一个次构造方法委托给主构造方法。使用this关键字将委托给相同类的另一个构造方法

class Person {
    constructor(parent: Person) { #如果是无参数的主构造方法,不用显式的调用
        parent.children.add(this)
    }
}
class Person(val name: String) {
    constructor(name: String, parent: Person) : this(name) { 显式的使用this
        parent.children.add(this)
    }
}

14、注意踩坑的又来了,那就是init代码块一定会执行,而且在你次构造方法之前执行

Note that code in initializer blocks effectively becomes part of the primary constructor. Delegation to the primary constructor happens as the first statement of a secondary constructor, so the code in all initializer blocks is executed before the secondary constructor body. Even if the class has no primary constructor, the delegation still happens implicitly, and the initializer blocks are still executed

注意,初始化代码块的代码有效地成为主构造方法的一部分。将委托给主构造方法作为次构造方法的第一个语句,因此初始化代码块的代码都在次构造方法之前执行。即使类没有主构造方法,委托仍然以隐式地进行,初始化代码块的代码仍然会被执行

15、一个class即没有主构造方法、又没有次构造方法,默认会生成一个public无参的主构造方法

If a non-abstract class does not declare any constructors (primary or secondary), it will have a generated primary constructor with no arguments. The visibility of the constructor will be public. If you do not want your class to have a public constructor, you need to declare an empty primary constructor with non-default visibility:

如果一个非抽象类,没有公开的任何构造方法(主构造方法或者次构造方法)它将会生成一个无参的主构造方法。这个主构造方法的可见性是public的,如果你不想你的class有public的主构造方法,你需要去声明一个空的主构造方法,而不是使用默认的可见性

class DontCreateMe private constructor () { ... }

16、思考一个问题,如果只有次构造方法,没有主构造方法,那么Kotlin会生成无参的构造方法吗?

试了一下,跟java类似,class中有了构造方法、无论是主构造方法、还是次构造方法,只要有了,默认就不会再生成无参的主构造方法了

class Cat{

    var age : Int = 0

    constructor( name : String, age : Int) { #这里我尝试使用 :this(),调用无参的主构造方法,发现根本就没有,证明,有了次构造方法,无参的主构造方法也没有了吧
        this.age = age
    }

}

17、总结

a、没想到在构造方法环节,Kotlin有创新,其实是代码结构更清晰了,好吧

b、可以只有次构造方法,没有主构造方法

c、可以同时存在两种

d、主于次构造方法都没有时,编译器生成默认无参的一个主构造方法

e、觉着半天还是官方文档介绍的清楚,看来学习语言,还是去官方的比较好

再次记下官方地址:http://kotlinlang.org/docs/reference/classes.html

猜你喜欢

转载自blog.csdn.net/cadi2011/article/details/85761863