1.类的定义,kotlin中依旧使用关键字class声明类,类声明由类名、类头(指定其类型参数、主构造函数等)以及由花括号包围的类体构成。类头与类体都是 可选的;如果一个类没有类体,可以省略花括号。

//1.简单定义
class Invoice { /*......*/ }
//2.没有类体时
class Empty

2.构造函数,在 Kotlin 中的一个类可以有一个主构造函数以及一个或多个次构造函数。主构造函数是类头的一部分

//1. 它跟在类名(与可选的类型参数)后
class Person constructor(firstName: String) { /*......*/ } //2. 如果主构造函数没有任何注解或者可⻅性修饰符,可以省略这个 constructor 关键字。
class Person(firstName: String) { /*......*/ } //3.主构造函数不能包含任何的代码。初始化的代码可以放到以 init 关键字作为前缀的初始化块(initializer blocks)中。
// 在实例初始化期间,初始化块按照它们出现在类体中的顺序执行,与属性初始化器交织在一起 class InitOrderDemo(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}")
}
}

输出结果:

First property: 1
First initializer block that prints 1
Second property:1
Second initializer block that prints 1
 

主构造的参数可以在初始化块中使用。它们也可以在类体内声明的属性初始化器中使用

class Customer(name: String) {
val customerKey = name.toUpperCase()
}

声明属性以及从主构造函数初始化属性,也可以如此写

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

与普通属性一样,主构造函数中声明的属性可以是可变的(var)或只读的(val)。

如果构造函数有注解或可⻅性修饰符,这个 constructor 关键字是必需的,并且这些修饰符在它前面

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

3.次构造函数:可以声明前缀有constructor的次构造函数

class Person {
var children: MutableList<Person> = mutableListOf<>()
constructor(parent: Person) {
parent.children.add(this)
}
}

如果类有一个主构造函数,每个次构造函数需要委托给主构造函数,可以直接委托或者通过别的次构造 函数间接委托。委托到同一个类的另一个构造函数用 this 关键字即可:

class Person(val name: String) {
var children: MutableList<Person> = mutableListOf<>()
constructor(name: String, parent: Person) : this(name) {
parent.children.add(this)
}
}

构造函数的运行顺序,是先运行主构造函数,即使为声明,如果有init代码块,也会在次构造函数体之前执行,其实跟java的代码块逻辑相同

class Constructors { 

   init {
println("Init block")
} constructor(i: Int) {
println("Constructor")
} }

运行结果

Init block
     Constructor


4.创建类,就像普通函数一样调用,在kotlin中没有new关键字

val invoice = Invoice()
val customer = Customer("Joe Smith")

5.kotlin中所有类的超类为 Any ,存在三个方法 equals() 、hashCode() 与 toString(),默认情况下kotlin中所有的类都是final,如果需要被继承,则需要加open

 open class Base //Class is open for inheritance

 //例:
open class Base(p: Int)
class Derived(p: Int) : Base(p) //注意:如果派生类有主构造函数,其基类必须用派生类主构造函数的参数就地初始化

6.覆盖方法,kotlin中对于可覆盖的成员(或成为open开放的)覆盖后的成员需要显示修饰符

open class Shape {
open fun draw() { /*......*/ }
fun fill() { /*......*/ }
} class Circle() : Shape() {
override fun draw() { /*......*/ }
} //Circle.draw() 函数上必须加上 override 修饰符。
//如果没写,编译器将会报错。如果函数没有标 注open如 Shape.fill(),那么子类中不允许定义相同签名的函数,不论加不加override。将 open 修饰符添加到 final 类(即没有 open 的类)的成员上不起作用。
//标记为 override 的成员本身是开放的,也就是说,它可以在子类中覆盖 //如果想禁止再次被覆盖,使用final关键字
open class Rectangle() : Shape() {
final override fun draw() { /*......*/ }
}

7.覆盖属性,于覆盖方法,基本一样

//1.例子
open class Shape {
open val vertexCount: Int = 0
}
class Rectangle : Shape() {
override val vertexCount = 4
} //2.例子
interface Shape {
val vertexCount: Int
}
class Rectangle(override val vertexCount: Int = 4) : Shape // 总是有 4 个顶点 class Polygon : Shape {
override var vertexCount: Int = 0 // 以后可以设置为任何数,val变为了var
}

注意:设计一个基类时,应该避免在构造函数、属性初始化器以及 init 块中使用 open 成员。

8.调用超类实现

8.1 派生类中可以通过super调用超类中的函数和属性访问器

open class Rectangle {
open fun draw() { println("Drawing a rectangle") }
val borderColor: String get() = "black"
} class FilledRectangle : Rectangle() {
override fun draw() {
super.draw()
println("Filling the rectangle")
}
val fillColor: String get() = super.borderColor
}

8.2在内部类中访问外部类的超类,可以通过外部类名限定的super关键字来实现:super@Outer

class FilledRectangle : Rectangle() {
override fun draw() { /* ...... */
} override val borderColor: String get() = "black" inner class Filler {
fun fill() { /* ...... */
} fun drawAndFill() {
super@FilledRectangle.draw() // 调用 Rectangle 的 draw() 实现 fill()
println("Drawn a filled rectangle with color${super@FilledRectangle.borderColor}") // 使用 Rectangle 所实现的 borderColor 的 get()
}
}
}

9.覆盖规则在 Kotlin 中,实现继承由下述规则规定:如果一个类从它的直接超类继承相同成员的多个实现,它必须 覆盖这个成员并提供其自己的实现(也许用继承来的其中之一)。为了表示采用从哪个超类型继承的实 现,我们使用由尖括号中超类型名限定的 super,如 super<Base>

open class Rectangle {
open fun draw() { /* ...... */ }
}
interface Polygon {
fun draw() { /* ...... */ } // 接口成员默认就是“open”的
}
class Square() : Rectangle(), Polygon {
// 编译器要求覆盖 draw():
override fun draw() {
super<Rectangle>.draw() // 调用 Rectangle.draw()
super<Polygon>.draw() // 调用 Polygon.draw()
}
}

10.抽象类,在kotlin中可以用抽象类/成员去覆盖一个非抽象的类/成员

open class Polygon {
open fun draw() {}
} abstract class Rectangle : Polygon() {
abstract override fun draw()
}

11.伴生对象 如果你需要写一个可以无需用一个类的实例来调用、但需要访问类内部的函数(例如,工厂方法),你可 以把它写成该类内对象声明中的一员。

更具体地讲,如果在你的类内声明了一个伴生对象,你就可以访问其成员,只是以类名作为限定符。

kotlin类和对象—>类与继承的更多相关文章

  1. python的类和对象——类的静态字段番外篇

    什么是静态字段 在开始之前,先上图,解释一下什么是类的静态字段(我有的时候会叫它类的静态变量,总之说的都是它.后面大多数情况可能会简称为类变量.): 我们看上面的例子,这里的money就是静态字段,首 ...

  2. java基础:详解类和对象,类和对象的应用,封装思想,构造方法详解,附练习案列

    1. 类和对象 面向对象和面向过程的思想对比 : 面向过程 :是一种以过程为中心的编程思想,实现功能的每一步,都是自己实现的 面向对象 :是一种以对象为中心的编程思想,通过指挥对象实现具体的功能 1. ...

  3. Java自学-类和对象 类属性

    Java的类属性和对象属性 当一个属性被static修饰的时候,就叫做类属性,又叫做静态属性 当一个属性被声明成类属性,那么所有的对象,都共享一个值 与对象属性对比: 不同对象的 对象属性 的值都可能 ...

  4. java学习-初级入门-面向对象③-类与对象-类与对象的定义和使用1

    今天学习类与对象.先大致解释一下类与对象的含义. 对象:object 有物体这一概念,一切皆对象(物体),对象由静态的属性和动态的行为组成. 比如说水杯: 水杯的静态属性:材质,容量,质量,颜色 动态 ...

  5. python的类和对象——类成员番外篇

    学完了面向对象的三大特性,已经get了所有屌丝技能的我们也当一回文艺小青年,来看看类的成员和成员修饰符. 今天‘三’这个数字好亲和~~~类成员可以分为三类:字段.方法和属性 一.字段 首先我们来看看字 ...

  6. java学习-初级入门-面向对象⑤-类与对象-类与对象的定义和使用3

    这次我们要做一个日期类Date类 主要目的是    1.  熟悉-->构造不同参数的函数  2.善于利用已有的函数!! 题目要求: Date类要求 可设定年月日 可转换为字符串,并可指定分隔符, ...

  7. java学习-初级入门-面向对象④-类与对象-类与对象的定义和使用2

    我们继续学习类与对象,上一篇我们定义了  坐标类(Point), 这次我们在Point的基础上,创建一个圆类(Circle). 案例:创建一个圆类 题目要求: 计算圆的周长和面积:求判断两个圆的位置关 ...

  8. 类与对象 && 继承

      以下是本人的对类与对象.继承的一些理解,如有错误之处万望谅解,如有朋友愿意指正,十分乐意,万分感谢!   类与对象     类与对象是学习编程的基础(大概吧),那么何为类?何为对象呢?   一.简 ...

  9. ES6学习笔记(二):教你玩转类的继承和类的对象

    继承 程序中的继承: 子类可以继承父类的一些属性和方法 class Father { //父类 constructor () { } money () { console.log(100) } } c ...

  10. C#程序设计基础——类、对象、方法

    类与对象 类 类是一种构造,通过使用该构造,用户可以将其他类型的变量.方法和事件组合在一起,从而创建自定义类型.类就像一个蓝图,它定义类型的数据和行为. 对象 定义类之后,便可通过将类加载到内存中来使 ...

随机推荐

  1. 【Spring-Cloud】Nacos2.0.3 单系统集群部署问题汇总

    1.强制要求JDK8版本 且 64位 C:\Users\Administrator\Desktop\Nacos-Server\Nacos-2.0.3-8848\bin>java -version ...

  2. 【H5】02 <head>头标签介绍

    摘自: https://developer.mozilla.org/zh-CN/docs/Learn/HTML/Introduction_to_HTML/The_head_metadata_in_HT ...

  3. 【Vue】Re19 Promise

    一.概述 Promise是异步编程的解决方案 异步事件的处理: 封装的异步请求函数不能立即获取结果, 通常会传入另外一个函数,在请求成功的时候将数据通过传入的函数回调出去 如果只是一个简单的请求,那么 ...

  4. Trump 黑马 or 搅局者? 讲座视频分享

    沈逸-特朗普能走多远   https://www.bilibili.com/video/BV1r7411t7VS/?spm_id_from=333.788.videocard.2     国际关系 对 ...

  5. C# 工厂模式 个人基本流程

    有个前提 本文并不会介绍工厂模式,只是记录在实际当中个人比较喜欢的工厂写法.仅仅作为备忘和参考. 开始流程 定义一个抽象类,包含一些公共的业务逻辑(也可以是接口) /// <summary> ...

  6. java获取包下所有的类

    1.背景 给一个Java的包名,获取包名下的所有类.. 根据类上的注解,可以展开很多统一操作的业务 2.直接看代码-spring环境下 package com.qxnw.digit.scm.commo ...

  7. stm32 F103C8T6 4x4矩阵键盘使用

    首先感谢 江科大 的stm32入门课程 受益匪浅.推荐有兴趣的朋友去看看. 先看看我用的矩阵键盘是啥样的(很常见的一种) 接线如图(其他型号根据自己需求接上GPIO口) 代码基于stm大善人的代码修改 ...

  8. CH03_布局

    第3章:布局 本章目标 理解布局的原则 理解布局的过程 理解布局的容器 掌握各类布局容器的运用 理解 WPF 中的布局 WPF 布局原则 ​ WPF 窗口只能包含单个元素.为在WPF 窗口中放置多个元 ...

  9. .NET 轻量化定时任务调度 FreeScheduler

    前言 在平时项目开发中,定时任务调度是一项重要的功能,广泛应用于后台作业.计划任务和自动化脚本等模块. FreeScheduler 是一款轻量级且功能强大的定时任务调度库,它支持临时的延时任务和重复循 ...

  10. luoguP3330 [ZJOI2011] 看电影--组合数学--高精度

    \(luoguP3330\) [ZJOI2011] 看电影 废了老命想题解 $$luogu$$ $$HZOI$$ 题意 到了难得的假期,小白班上组织大家去看电影.但由于假期里看电影的人太多,很难做到让 ...