在 Kotlin 中所有类都有一个共同的超类 Any.
1.类关键字
1.kotlin 类使用关键字class
class Animi{
}
2.kotlin 的类默认是final的,如果这个类允许被继承,必须使用open关键字修饰类。
open class Animi{
}
2.kotlin 的构造函数:
kotlin的构造函数包含主构造函数和次构造函数。
Tips:
- 主构造函数最多只能有一个,也可以没有,默认会有一个无参的。
- 次构造函数可以有一个或多个或0个。
- 主构造函数中不能有任何代码,初始化可以在初始化块中,初始化块是主构造函数的一部分。
- 如果类有主构造函数,则所有的次构造函数都要委托于主构造函数。可以直接委托给主构造函数,也可以间接的通过其他次构造函数委托给主构造函数。
- 委托到同一个类的另一个构造函数用 this 关键字即可
构造函数的关键字:constructor
主构造函数跟在类名的后面:
class Test //无类体,省略{}
class Test(){} //显示,默认无参构造
class Test {} //隐式,默认无参构造
class Test constructor(str : String){} //显示主构造函数写法
class Test(str : String){} //省略constructor关键字,主构造函数的隐式写法
class Test private constructor(str : String,abs : Int){} //含有修饰符不能使用隐式写法
class Test @inject private constructor(str : String,abs : Int){} //含有注解修饰符不能使用隐式写法
类体中可以再添加次构造函数:
Tips:
- 默认构造函数的可见性是public的,但是你可以修改其可见性;
- 非抽象类,如果没有显示的声明构造函数,默认会生成一个无参构造函数。
- 在 JVM 上,如果主构造函数的所有的参数都有默认值,编译器会生成 一个额外的无参构造函数,它将使用默认值。
- 带有修饰符/注解的主构造函数,需要使用constructor关键字。
1.当类只有一个构造函数时,使用init完成构造函数。主构造函数没有任何注解或者可见性修饰符,可以省略这个 constructor 关键字。
class Animi(i : Int , type : String){
init{
abs(i , type)
}
fun abs(count : Int , type : String){
var co=count;
val tt = type
}
}
2.当有多个不同的构造函数,但是没有主构造函数时,使用construction关键字
class Fruit {
constructor(name: String, leve: String) {}
constructor(name: String, leve: String, number: Int) : this(name, leve) {}
}
3.当类有主构造函数时,所有的次构造函数都必须要,使用this关键字,直接或间接委托主构造函数。
class Fruit(name: String) { //主构造函数
constructor(name: String, leve: String) : this(name) {// 次构造函数1 }
constructor(name: String, leve: String, number: Int) : this(name, leve) {// 次构造函数2 }
}
4.带默认值的主构造函数
class Fruits(var name: String = "PingGuo", val leve: Int? = 1, val number: Int? = 10, address: String = "YT") {
//主构造函数的参数可以直接当属性来使用
val MyName = name;
val Num = number;
override fun toString(): String {
return "Name=" + MyName + "Num=" + Num + "Leve=" + leve;
}
}
5.可见性为private 的主构造函数,使用次构造函数的委托进行赋值
class A private constructor(name: String) {
val Name = name
var Num: Int = 0
constructor(name: String, num: Int) : this(name) {
this.Num = num
}
fun NameXX(): String {
return Name + "XXX"
}
}
3.类的成员
- 构造函数和初始化块
- 函数
- 属性:含有初始器、get访问器和set访问器,但都是可选
- 嵌套类和内部类
- 对象的声明
class Person {
var name: String? = "Testing" //属性
var Address: String? = "zhangxinglu" //含有get的属性
get() = Address
var AddressisEmpty: Boolean
get() = this.Address!!.length == 0
set(value) {
AddressisEmpty = value
}
var setterVisibility: String = "abc"
private set // 此 setter 是私有的并且有默认实现
var setterWithAnnotation: Any? = null
@Inject set // 用 Inject 注解此 setter
var size:Int = 0
val isEmpty get() = this.size == 0 // 具有类型 Boolean
companion object { //伴生对象
var Handler_Tag_P = "Post"
var Handler_Tag_G = "Get"
fun getInstance(): Person {
return Person()
}
}
fun printName() { //函数
System.out.print("name :>>" + name)
}
}
4.继承
在 Kotlin 中所有类都有一个共同的超类 Any ,这对于没有超类型声明的类是默认超类,Any 类:它除了 equals() 、 hashCode() 和 toString() 外没有任何成员。
tips 继承的规则:
如果一个类从它的直接超类继承相同成员的多个实现, 它必须覆盖这个成员并提供其自己的实现(也许用继承来的其中之一)。 为了表示采用
从哪个超类型继承的实现,我们使用由尖括号中超类型名限定的 super:
super<Base> :
类和继承
open class A {
open fun f() { print("A") }
fun a() { print("a") }
}
interface B {
fun f() { print("B") } // 接口成员默认就是“open”的
fun b() { print("b") }
}
class C() : A(), B {
// 编译器要求覆盖 f():
override fun f() {
super<A>.f() // 调用 A.f()
super<B>.f() // 调用 B.f()
}
}
open class A { //默认含有一个无参构造函数
open fun cctest(){
//默认为final方法,如果需要继承就需要使用open修饰
}
}
class B : A() {
final override fun cctest() {//不加final 则可以在子类中继续覆盖,添加final修饰符,就不允许子类继续覆盖
super.cctest()
}
override fun equals(other: Any?): Boolean {
return super.equals(other)
}
override fun hashCode(): Int {
return super.hashCode()
}
override fun toString(): String {
return super.toString()
}
}
有参构造函数的继承
//有参构造函数
open class c(name: String){
open val x: Int get() { //get方法的属性覆盖
return 0
}
open val y: Int get() { //get方法的属性覆盖
return -1
}
}
//子类同样包含,有参构造函数
class d(val name: String) : c(name) {
init {
abs(name)
}
fun abs(name: String?) {
var ne = name
}
fun tabs() {
val na = this.name
}
}
//子类没有有参主构造函数,此构造函数就必须使用super关键字初始化基类或者委托给其他次构造函数初始化基类
class f : c {
constructor(name: String) : super(name) //super初始化父类的基类
constructor(name: String, type: String) : super(name)
constructor(name: String, type: String, num: Int) : this(name, type) //委托给其他积累实现
override val x: Int = 90
override var y: Int = 190 //用var 属性覆盖一个val,反之是不可以的
}
5.抽象类 abstract class
类中某些成员可以声明为abstract,抽象成员在本类中可以不用实现。
open class Base {
open fun f() {}
}
//抽象成员覆盖一个非抽象的开放成员
abstract class Derived : Base() {
override abstract fun f()
}
6. 伴生对象(相当于Java中的静态方法/对象)
class Person {
companion object { //伴生对象
var Handler_Tag_P = "Post"
var Handler_Tag_G = "Get"
fun getInstance(): Person {
return Person()
}
}
}
使用伴生对象:
class Max{
var p = Person.getInstance() //调用伴生对象的方法
fun print(){
System.out.print("Handler 1:>>"+Person.Handler_Tag_G) //调用伴生对象的属性
System.out.print("Handler 2:>>"+Person.Handler_Tag_P)
}
}
6.编译期常量
已知值的属性可以使用 const 修饰符标记为 编译期常量。
这些属性需要满足以下要求:
- 位于顶层或者是 object 的一个成员
- 用 String 或原生类型 值初始化
- 没有自定义 getter
这些属性可以用在注解中:
const val SUBSYSTEM_DEPRECATED: String = "This subsystem is deprecated"
@Deprecated(SUBSYSTEM_DEPRECATED) fun foo() { …… }
7.延迟初始化属性
关键字:lateinit
- 该修饰符只能用于在类体中(不是在主构造函数中)声明的 var 属性
- 并且仅当该属性没有自定义 getter 或 setter 时
- 该属性必须是非空类型,并且不能是原生类型。
在初始化前访问一个 lateinit 属性会抛出一个特定异常,该异常明确标识该属性被访问及它没有初始化。
public class MyTest {
lateinit var subject: TestSubject
@SetUp fun setup() {
subject = TestSubject()
}
@Test fun test() {
subject.method() // 直接解引用
}
}