1.次构造函数
可以理解为是在对主构造函数进行”重载“,但是必须要直接或间接代理上主构造函数,使得主构造函数的值传入次构造中;
open class Person(var a1 : Int) {
constructor(a2 : String) : this(0) {
}
constructor(a1 : Int, a2 : Int) : this(a1){
}
}
2.open关键字
只有被open修饰的类,才可以被继承。被open修饰的方法,才能被重写.被open修饰的属性,才能够被重写(属性被open修饰后,必须初始化,不能被lateinit修饰,也不能只在init中被初始化)
open class Person(var a1 : Int) {
open fun test(){}
open var time : Int
}
3.类的修饰符
- classModifier: 类属性修饰符,标示类本身特性。
final // 类不可继承,默认属性
open // 类可继承,类默认是final的
abstract // 抽象类
enum // 枚举类
annotation // 注解类
- accessModifier: 访问权限修饰符
private // 仅在同一个文件中可见
protected // 同一个文件中或子类可见
public // 所有调用的地方都可见
internal // 同一个模块中可见
4.子类继承
子类有主构造函数, 则基类必须在主构造函数中立即初始化。
子类没有主构造函数,则基类可以在类头或次构造函数中初始化
open class Person(var a1 : Int) {
}
//子类有主构造函数
class child(a1 :Int) : Person(100){
}
//子类没有主构造函数
class man : Person(100) {
}
class felman : Person{
constructor(a1 : Int) : super(101){
}
}
5.属性重写
你可以用一个var属性重写一个val属性,但是反过来不行。因为val属性本身定义了getter方法,重写为var属性会在衍生类中额外声明一个setter方法(子类重写父类属性,也就相当于必须重写该属性的 getter 和 setter 方法,而子类中的 val 不能有 setter 方法,所以无法“覆盖”父类中 var 的 setter 方法,相当于缩小了父类中相应属性的使用范围,是不允许的,就像我们不能把父类中一个 public 方法重写成 private 方法一样。)
6.拓展函数
对类的属性和方法进行拓展,不需要继承和装饰器模式
一种静态行为,对被扩展的类代码本身不造成任何影响
class Test {
var num = 1
}
fun Test.goo(){
println("${num}")
}
fun <T> MutableList<T>.len() : Int {
return this.size
}
拓展函数是静态解析的
open class C
class D: C()
fun C.foo() = "c" // 扩展函数 foo
fun D.foo() = "d" // 扩展函数 foo
fun printFoo(c: C) {
println(c.foo()) // 输出 c
}
若扩展函数和成员函数一致,则使用该函数时,会优先使用成员函数。
7.泛型
泛型:将类型作为一个参数使用,可以用在类,接口,方法上
使用 out 使得一个类型参数协变,协变类型参数只能用作输出,可以作为返回值类型但是无法作为入参的类型:
in 使得一个类型参数逆变,逆变类型参数只能用作输入,可以作为入参的类型但是无法作为返回值的类型:
class test2<out T>(val time : T){
fun getTime() : T{
return time
}
}
class test3<in T>(){
fun getTime(time : T){
}
}
8.数据类在结构声明中使用
data class User(
var name : String,
var age : Int
)
fun main() {
val jane = User("jane", 35)
val(name, age) = jane
println("$name, $age is ")
}
9.密封类
和枚举的对比
enum class Color(var lab : Int, var namex : String){
RED(0xFF0000, "red"), //每个实例携带的信息相同
GREEN(0x00FF00, "green"),
BLUE(0x0000FF, "blue")
}
sealed class Users{
object Unknown : Users()
data class Man(val age: Int) : Users() //实例可携带不同的信息
data class Felman(val name: String) : Users()
}
每个枚举常量只存在一个实例,而密封类的一个子类可以有可包含状态的多个实例。
密封类通常和when搭配使用
sealed class Users{
object Unknown : Users()
data class Man(val age: Int) : Users()
data class Felman(val name: String) : Users()
}
fun getSex(users: Users) : Int = when(users){
Users.Unknown -> 0 //没有额外参数时,不用is
is Users.Man -> 1
is Users.Felman -> 2 //因为涵盖了所有实例分支,所以不用else
}
10,枚举类实现单例,每个枚举常量只存在一个实例
枚举类已经隐式地继承了Enum类,所以枚举类不能继承其他类,但是可以实现接口
enum class Singleton{
INSTANCE;
}
// 编译器生成的Java代码(简化版)
public final class Singleton extends Enum<Singleton> {
public static final Singleton INSTANCE = new Singleton();
private Singleton() {
// 私有构造函数
}
// 其他枚举相关方法...
}