1.密封类
密封类(sealed class)
①密封类用来表示受限的类继承结构,对密封类中的某个值来说,它所属类型只能是受限的类型之一,不能是其他类型。
②在某种意义上,他们是枚举类的扩展:枚举类型的值集合也是受限的,但每个枚举常量只存在一个实例,而密封类的一个子类可以有可包含状态的多个实例。
③要声明一个密封类,需要在类名前面添加 sealed 修饰符。虽然密封类也可以有子类,但是所有子类都必须在与密封类自身相同的文件中声明。(在 Kotlin 1.1 之前,该规则更加严格:子类必须嵌套在密封类声明的内部)。
④密封类本身是一个抽象的类,因此它是不能被直接实例化的,而密封类本身里面可以包含一些抽象的成员的,同时密封类不允许提供
非私有的构造方法。换句话说,密封类构造方法默认情况下是私有的。
使用密封类的关键好处在于使用 when 表达式 的时候,如果能够验证语句覆盖了所有情况,就不需要为该语句再添加一个 else 子句了。
- 示例代码
sealed class Calculator
class Add : Calculator()
class Subtract : Calculator()
class Multiply : Calculator()
fun calculate(a: Int, b: Int, cal: Calculator) = when (cal) {
is Add -> a + b
is Subtract -> a - b
is Multiply -> a * b
}
fun main(args: Array<String>) {
println(calculate(1, 2, Add()))
println(calculate(1, 2, Subtract()))
println(calculate(1, 2, Multiply()))
}
- 运行结果
3
-1
2
2.Kotlin泛型
泛型(generics),表示变量类型的参数化
- 示例代码
class MyGenerics<T>(t: T){
var variable: T
init {
this.variable = t
}
}
fun main(args: Array<String>) {
//var myGeneric:MyGenerics<String> = MyGenerics<String>("helloworld")//完整写法
var myGeneric = MyGenerics("helloworld")//借助于kotlin的类型推断
println(myGeneric.variable)
}
- 运行结果
helloworld
3.协变(convariant)与逆变(controvariant)
- 关于协变与逆变的概念及来源
//例如List<Object>与 List<String>
List<String> list = new ArrayList();
List<Object> list2 = list;//编译失败,List<String> 并不是 List<Object> 的子类型。
list2.add(new Date())
String str = list.get(0)//ClassCastException:类型转换错误
List<? extends Object> list ... //可以放Object类型及子类型
//例如Collection 接口中的 addAll()方法
//直观理解
interface Collection<E>{
void addAll(Collection<E> items)
}
void copyAll(Collection<Object to,Collection<String> from){
to.addAll(from);//编译失败,Collection<String> 不是 Collection<Object> 的子类型
}
//实际情况
interface Collection<E>{
void addAll(Collection<? extends E> items;
}
Collection<String>就是Collection<? extends Obejct>的子类型 //协变
List<? super String> //逆变
我们如果只从中读取数据,而不往里面写入内容,那么这样的对象叫做生产者(协变);如果只向里面写入数据,而不从中读取数据,那么这样的数据叫做消费者。(逆变)
生产者使用 ? extends E; 消费者使用? super E
- 示例代码
class MyClass<out T,in M>(t: T,m: M){
private var t: T
private var m: M
init {
this.t = t
this.m = m
}
fun get(): T = this.t
fun set(m: M){
this.m = m
}
}
fun myTest(myClass: MyClass<String,Number>){
var myObject: MyClass<Any,Int> = myClass
println(myObject.get())
}
fun main(args: Array<String>) {
var myClass = MyClass<String,Number>("abc",2);
myTest(myClass)
}
- 运行结果
abc
kotlin中针对协变与逆变提供了两个关键字out与in。
网友评论