Kotlin Class, object, and interfaces
Kotlin中的接口:interface关键字 不同于java方法的implement和extends,kotlin使用的是冒号: 来完成这个方法。 也不同与java的注释override,我们使用关键词override来强制实现。
接口默认实现:
interface Clickable{
fun click() // 方法声明
fun showOff() = println("i am clickable") // 接口默认实现
}
复制代码
对于接口默认实现的方法:
- 我们可以直接使用
- 我们也可以重写这个方法
interface Focusable{
fun setFocus(b: boolean) = println("I ${if(b) "got" else "Losr"} focus")
fun showOff() = println("i'm foucusable! ")
}
复制代码
如果一个类实现了多个接口,而多个接口却有相同的方法,我们需要具体指定实现哪一个方法
class Button: Clickable, Focusable{
override fun click() = println("I was clicked")
override fun showOff(){
super<Clickable>.showOff()
super<Focusable>.showOff()
}
}
复制代码
final by default
kotlin中的类默认都是final ,在Effective java中提到了一点:『design and document for inheritance or else prohibit it』
// 这个类可以被其他类继承
open class RichButton: Clickable {
fun disable(){} // fun 默认是final 表示这个方法可以被复写
open fun animate(){} // open fun 表示你可以复写这个方法
override fun click(){} // 这个方法复写一个open fun 它同样也是open fun 可以被人复写
final override fun click1(){} // 但是被final修饰了 所以不可以被其他复写
}
复制代码
abstract
和java一样 abstract表示的是这个类不可以被实例化,一个抽象类可以包含抽象对象和抽象方法,抽象类中的所有的方法都是open
abstract class Animated{
abstract fun animate()
open fun stopAnimating(){}
fun animateTwice(){}
}
复制代码
modifier | corresponding member | Comments |
---|---|---|
final | can't be overridden | Used by default |
open | Can be overridden | Should be specified |
Abstract | Must be overridden | Can be used only in abstract class |
override | overrides a member in superclass | Overrideen member is open by default if not marked final |
pubic by default
kotlin只有三个标识修饰关键字:public protected private。 去掉了java中的package-private,在Kotlin中packages只是在namespace中来组织代码而已。
modifier | class member | Top-level declaration |
---|---|---|
public | visible everywhere | Visible everywhere |
Protected | visible in subclassed | |
private | visible in a class | visible in a file |
Inner And nested class: nested by default
Kotlin中的嵌套类不能访问外部类的对象实例,
interface State : Serializable
interface View{
fun getCurrentState() : State
fun restoreState(state: State){}
}
public class Button implements View{
public State getCurrentState(){
return new ButtonState();
}
public void restoreState(State state){}
public class ButtonState implement State{}
}
复制代码
在很多常见的场景,我们都需要创建一个内部类来存储外部类的状态,在上面的代码中当我们调用getCurrentState()来序列化我们会报错,因为这里面有一个问题便是 内部类ButtonState实现了State这个可以序列化的同时其实它还隐藏的持有了外部类的引用 因为Button没有实现序列化的接口导致报错。
class A declared whthin another class B | In Java | In Kotlin |
---|---|---|
Nested class | State class A | class A |
Inner class | class A | Inner class A |
sealed 关键字
我们都知道enum枚举 表示有限的集合,但是enum对应的其实是基本数据类型。在kotlin中类的表达其实是sealed,两者高度相似。
类中的constructor
kotlin中的构造函数分为两种,因为kotlin中允许可以默认参数 所以kotlin的写法中不太需要过载方法 一般只需要设置一些默认参数就可以
// kotlin中的原创写法 简洁不少 去掉了constructor 同时不用申明变量
class User(val nickName: String)
// 想java一种使用关键词constructor init super this
class User constructor(_nickname: String){
val nickname:String
//此处初始化可以多次使用 按照声明的顺序按顺序执行
init{
nickname = _nickname
}
init{
nick
}
}
class MyButton : View{
constructor(ctx: Context):super(ctx){
}
}
复制代码
interface中的变量
interface User{
val nickName: String
}
复制代码
接口中的声明的变量如何去初始化
class PrivateUser(override val nickname:String) :User
class SubscribeingUser(val email: String) : User{
override val nickname;String
get() = email.substringbefore('@')
}
class FaceBookUser(val accountId: Int) : User{
override val nickname = getFacebookName(accountId)
}
复制代码
类的装饰模式 by 关键字
class DelegatingCollection<T>(innerList: Collection<T> = ArrayList<T>()):Collection<T> by innerList
复制代码
类的单例模式 object 关键字
- 类的单例模式
object Payroll{
val allEmployees = arrayListOf<Person>()
fun calculateSalary(){
for(person in allEmployees){
}
}
}
复制代码
object 中的对象没有所谓的构造器,对象的生成在定义的时候就会立即生成,而不是通过偶在函数来生成的
object的对象的调用之间使用 . 即可,这一点和javascript中的字面对象有点像
Payroll.allEmployees.add(Person(...))
Payroll.calculateSalary()
复制代码
Object 对象也可以被类继承和接口实现。
-
Static 静态方法和对象
直接创建一个工厂模式 也就是所谓的静态方法
class User(val nickname: String){ companion object{ fun newBeginingUser(email:String) = User("") fun newFacebookUser(accountId: Int) = User(account) } } 复制代码
使用方法:
val subscribeingUser = User.newBeginingUser("bob@email.com") val facebookUser = User.newFacebookUser(3) 复制代码
-
匿名内部类
Object可以充当一个匿名内部类来使用
window.addMouselistener(object: MouseAdapter(){ ... }) 复制代码
Summary
- Interface 在Kotlin中和Java类似 除了可以拥有默认的方法实现和属性
- 所有的声明默认都是 final public
- 想让声明不是final 需要使用关键open
- Nested class 默认是不外部类有引用关系, 可以使用关键字 inner 来内部类与外部类有引用关系
- 关键字 sealed 可以将有限的子类包含在父类中(在when 中可以去掉else 因为包含了所有的可能性)
- 除了 第一构造函数外,我们还有 init constructor 来灵活初始化对象
- field 可以提供便捷的对象的set() get()方法的使用
- data 也就是所谓的Javabean 关键字可以提供 equals hashCode toString copy 等便捷的方法
- by 关键字可以提供类似代理模式
- object 关键字 可以提供单例模式
- companion object 替代了java所有的静态方法和属性定义
- object 关键字可以替代java中的匿名内部类