Kotlin语法(六)-类和继承

来源:互联网 发布:淘宝达人直播怎么赚钱 编辑:程序博客网 时间:2024/06/07 03:44

1.     声明类

         Kotlin使用关键字*class *{:.keyword}声明类。类声明包括类名、类头(指定其类型参数,主构造函数等)和这个类的主干。类头和主体都是可选的。

class Invoice {

}

 

//空类,可以省略花括号

class Empty

2.     构造函数

        在Kotlin中的类可以有主构造函数 和一个或多个二级构造函数。 

        -主构造函数是类头的一部分,它跟在这个类名后面(和可选的类型参数),使用“constructor”关键字。

class Person constructor(name:String) {

}

 

        -如果这个主构造函数没有任何注解或者可见的修饰符,这个constructor{: .keyword }关键字可以被省略。

class Person (name:String) {

}

 

         -相反,如果primary constructory有注解或者可见的指示符,constructor是必须的。

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

 

         -这个主构造函数不能包含任何的代码。初始化的代码可以被放置在initializer blocks(初始的模块),以init为前缀作为关键字{:.keyword}

class Person (name:String) {

    init {

        println("name is $name")

    }

}

 

        -在主构造函数里,可以直接用这些参数变量赋值给类的属性,或者用构造代码块来实现初始化

class Person (name: String) {

  varname: String

 

 init {

   this. name = name

  }

}

 

        -可以直接把primary constructor中的参数直接声明成为类的属性,定义的方法是在参数名前加上 var 或者 val 关键字,val 是代表属性是常量。在创建类的时候,调用构造函数就直接把它们进行了初始化,这样就不用在类中单独声明类的属性了。

class Person constructor(varname: String) {

}

//

var p1 = Person ("peaple-1")

println(p1.name) //print result:peaple-1

 

3.     扩展构造函数

        类也可以拥有被称为"二级构造函数"(为了实现Kotlin向Java一样拥有多个构造函数),通常被加上前缀"constructor"。

        secondary constructors,同样也是constructor开头,位于类体中。

class Person {

    constructor(parent: Person) {

    }

}

 

         如果类有一个主构造函数,每个二级构造函数需要委托给主构造函数,直接或间接地通过另一个二级函数。 委托到另一个使用同一个类的构造函数用this{: .keyword }关键字:

class Person (var name: String) {   

   //直接委托到主构造函数

   constructor(name: String, parent: Person) : this(name) {

}

//委托多一个二级构造函数

   constructor(age: Int, name: String, parent: Person) : this(name, parent){

}

}

 

         如果一个非抽象类没有声明任何构造函数(原发性或继发性),这将有一个生成的主构造函数不带参数。构造函数的可见性是public。如果你不希望你的类有一个公共构造函数,你需要声明与非缺省可见一个空的主构造函数:

class DontCreateMe private constructor () {

}

 

4.     创建类的实例

        要创建一个类的实例,我们调用构造函数,就好像它是普通的函数:

val invoice =Invoice() 

var p1 = Person("peaple-1")

 

5.     类成员

        类可以包括

       Ø  构造和初始化模块

       Ø  函数

       Ø  属性

       Ø  匿名和内部类

       Ø 对象声明
 

继承

1.     继承类

        在Kotlin所有的类中都有一个共同的父类Any,这是一个默认的父类且没有父类型声明:

classExample // Implicitly inherits from Any

 

         Any不属于java.lang.Object;特别是,它并没有任何其他任何成员,甚至连equals(),hashCode()和toString()都没有。

        

         要声明一个明确的父类,我们把类型放到类头冒号之后;父类可以(并且必须)在声明继承的地方,用原始构造函数初始化。

open class Base(p:Int) 

class Derived(p: Int) : Base(p)

         父类上的open{:.keyword}标注可以理解为Java中final{:.keyword}的反面,它允许其他他类 从这个类中继承。默认情况下,在Kotlin所有的类都是final。

 

         如果子类没有主构造,那么每个二级构造函数初始化基类型,使用super{:.keyword}关键字,或委托给另一个构造函数做到这一点。

         注意,在这种情况下,不同的二级构造函数可以调用基类型的不同的构造:

class MyView : View{

    constructor(ctx: Context) : super(ctx) {

    }

 

    constructor(ctx: Context, attrs:AttributeSet) : super(ctx, attrs) {

    }

}

 

2.     覆盖成员

        继承父类并覆盖父类函数时,Kotlin要求父类必须有open标注,被覆盖的函数必须有open标注,并且子类的函数必须加override标注。

open class Base {

  open fun v() {}

  fun nv() {}

}

 

class Derived() :Base() {

  override fun v() {}

}

 

         如果父类的这个函数没有标注open,则子类中不允许定义同名函数,不论加不加override。在一个final类中(即没有声明open的类),函数上也不允许加open标注。

         成员标记为override{:.keyword}的本身是开放的,也就是说,它可以在子类中重写。如果你想禁止重写的,使用final{:.keyword}关键字:

open classAnotherDerived() : Base() {

  final override fun v() {}

}

 

3.     重写的规则

        在Kotlin中,实现继承的调用通过以下规则: 如果一个类继承父类成员的多种实现方法,可以直接在子类中引用,它必须重写这个成员,并提供其自己的实现(当然也可以使用父类的)。

        为了表示从中继承的实现而采取的父类型,我们使用super{:.keyword}在尖括号,如规范的父名super<Base>:

open class A {

  open fun f() { print("A") }

  fun a() { print("a") }

}

 

interface B {

  fun f() { print("B") } // interfacemembers are 'open' by default

  fun b() { print("b") }

}

 

class C() : A(), B{

  // The compiler requires f() to beoverridden:

  override fun f() {

    super<A>.f() // call to A.f()

    super<B>.f() // call to B.f()

  }

}         类C同时继承A和B是可以的,而且我们在调用a()和b()函数时没有任何问题,因为他们在C的基类中只有一个实现。 但是f()函数则在A,B中都有实现,所以我们必须在C中覆盖f(),并且提供我们的实现以消除歧义。

 

抽象类

         跟Java一样,使用abstract关键字。         类和其中的某些实现可以声明为abstract{:.keyword}。 抽象成员在本类中可以不用实现。 因此,当一些子类继承一个抽象的成员,它并不算是一个实现:

abstract class A {

  abstract fun f() //不需要标注一个抽象类或者函数为open

}

 

interface B {

  open fun f() { print("B") }

}

 

class C() : A(), B{

  // We are not required to override f()

}

 

         另外:可以重写一个open非抽象成员使之为抽象的。

open class Base {

  open fun f() {}

}

 

abstract classDerived : Base() {

  override abstract fun f()

}

 

友元(伴侣)对象(Companion Objects)

         Kotlin 移除了 static 的概念。通常用 companion object 来实现类似功能。

classLaunchActivity {

  companionobject {

    val TAG: String =LaunchActivity::class.simpleName

 

    fun start(context: Context) {

      context.startActivity(Intent(context,LaunchActivity::class))

    }

  }

}

 

//

println("Startingactivity ${LaunchActivity.TAG}")

LaunchActivity.start(context)

 

类封闭(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()

}

 

//我们可以使用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 requiredbecause we've covered all the cases

}


0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 练科目三很紧张怎么办 驾照学员卡丢了怎么办 驾考时考试的车系统出错怎么办 驾驶证超期6个月怎么办 北京汽车年检只有电子保单怎么办 交电费户号9位数怎么办 扬州驾照12分扣完了怎么办 有大专毕业证在深圳怎么办居住证 微信解释包错误怎么办 富士康离职不批怎么办 到了怀孕年龄找不到工作怎么办 建筑公司挂靠发生人员伤残怎么办 外地生小孩落北京户口怎么办 户籍档案查不到直系亲属关系怎么办 考过了二建注册怎么办 异地工作辞职回家档案怎么办 离职怎么办档案放在人才市场 人才房住了6年后怎么办 医保辞职后断了怎么办 社保断了生育险怎么办 深圳小产权房水电费纠纷怎么办 有公租房的再婚怎么办 廉租房被没收了怎么办 商铺到期房东不续租怎么办 天津集体户口买不起房怎么办 房东不想续租了怎么办 唯一住房卖掉后户口怎么办 杭州唯一住房卖掉后户口怎么办 唯一一套住房卖掉户口怎么办 房租押金条丢了怎么办 二建证书跟毕业证丢失怎么办 住宅房到70年怎么办 护照号变了机票怎么办 苹果se指纹坏了怎么办 月经推迟怎么办才能快点来 车载支架不粘了怎么办 otpc平板电脑无法开机怎么办 手表表轴掉了怎么办 鸡肉放冰箱臭了怎么办 鸡胸肉熟了腥怎么办 梦幻西游手游手机号换了怎么办