类对象和接口
4.1 定义类继承结构
接口
//声明一个简单的接口
interface Clickable{
fun click()
fun showoff() = println(" i am Click") //继承后可以更改实现,也可以省略它
}
interface Focusable{
fun showoff() = println(" i mClick") //拥有相同的方法实现
fun setFocus(button: Button){
println(" i click $button focus")
}
}
class Button:Clickable,Focusable{
override fun click() {
println("Click")
}
}
报错:必须实现showoff方法
使用super
class Button:Clickable,Focusable{
override fun click() {
println("Click")
}
override fun showoff() {
// 使用super表明想要调用哪一个父类方法
super<Focusable>.showoff()
}
}
final ,open ,abstract 修饰符
koltin中类和方法默认是final的,防止出现 “脆弱基类”(对基类的修改会导致子类不正确的行为)发生
open class RichButton : Clickable {
fun disable() {} //这个函数是final,不能在子类中重写
open fun animate() {} // 这个函数是open 可以在子类中重写
override fun click() {//没有final的override是open的
}
}
abstract
abstract class Animation { // 这个类是抽象的,不能创建它的实例
abstract fun animate() // 这个函数是抽象的 没有实现,必须被子类重写
open fun stopAnimating() {} // 抽象类不是默认open 但可以标注为open
fun animateTwice() {}
}
class An : Animation(){
override fun animate() {
}
}
public
修饰符 | 类成员 | 顶层声明 |
---|---|---|
public(默认) | 所有地方可见 | 所有地方可见 |
internal | 模块中可见 | 模块中可见 |
protected | 子类中可见 | |
private | 类中可见 | 文件中可见 |
internal open class TalkativeButton : Focusable{
private fun yell() = println("yell")
protected fun whisper() = println("let is talk")
}
fun TalkativeButton.giveSpeech(){
/*
yell 方法的可见性:private 可见性意味着 yell 方法只能在 TalkativeButton 类的内部访问,不能在扩展函数 giveSpeech 中访问。
whisper 方法的可见性:protected 可见性意味着 whisper 方法只能在 TalkativeButton 类及其子类内部访问,不能在扩展函数 giveSpeech 中访问。
在 Kotlin 中,扩展函数并不是真正修改了类的定义,而是像一个静态函数一样被调用。因此,扩展函数无法访问类的私有成员或受保护成员(除非是在子类中)。
*/
}
报错:
可以将方法修改为public 或者在内部定义方法
internal open class TalkativeButton : Focusable {
public fun yell() = println("yell") // 改为 public
public fun whisper() = println("let's talk") // 改为 public
}
fun TalkativeButton.giveSpeech() {
yell()
whisper()
}
internal open class TalkativeButton : Focusable {
private fun yell() = println("yell")
protected fun whisper() = println("let's talk")
// 在类内部定义扩展函数
fun giveSpeech() {
yell()
whisper()
}
}
内部类和嵌套类
内部类
interface State:Serializable
interface ViewS {
fun getCurrentState(): State
fun resetCurrentState( state: State){}
}
class Buttons :ViewS{
override fun getCurrentState(): State = ButtonsState()
override fun resetCurrentState( state: State){}
class ButtonsState:State{}// 类似于java中静态嵌套类
}
类A在类B中声明 | 在java中 | 在kotlin中 |
---|---|---|
嵌套类(不存储外部类的引用) | static class A | class A |
内部类(存储外部类的引用) | class A | inner class A |
class Outer{
// 引用外部类实例,使用this@Outer从inner类中去访问Outer类
inner class Inner{
fun getOuter() :Outer = this@Outer
}
}
密封类
在 Kotlin 中,密封类(sealed class)是一种特殊的类,它用来表示受限的类层次结构。密封类的子类必须嵌套在密封类中,或者与密封类在同一个文件中定义。这使得密封类非常适合表示有限的、明确的类型集,通常用于表示有限的状态集或结果类型。
使用密封类的场景
-
表示状态或结果类型:密封类常用于表示一组有限的可能状态。例如,网络请求的结果可能是成功、失败或进行中。
-
简化 when 表达式:在处理密封类的子类时,when 表达式可以确保所有可能的子类都得到了处理,从而避免遗漏某些情况。
-
处理错误或异常:密封类可以用于表示一组有限的错误类型,这样可以在处理错误时提供更好的类型安全性。
1. 表示网络请求的结果
sealed class Result {
data class Success(val data: String) : Result()
data class Failure(val error: Exception) : Result()
object Loading : Result()
}
fun handleResult(result: Result) {
when (result) {
is Result.Success -> println("Data: ${result.data}")
is Result.Failure -> println("Error: ${result.error.message}")
is Result.Loading -> println("Loading...")
}
}
2. 表示有限状态的状态机
sealed class UiState {
object Loading : UiState()
data class Success(val data: List<String>) : UiState()
data class Error(val message: String) : UiState()
}
fun render(state: UiState) {
when (state) {
is UiState.Loading -> println("Loading...")
is UiState.Success -> println("Data: ${state.data}")
is UiState.Error -> println("Error: ${state.message}")
}
}
3. 处理错误类型
sealed class ErrorType {
object NetworkError : ErrorType()
data class ServerError(val code: Int) : ErrorType()
object UnknownError : ErrorType()
}
fun handleError(error: ErrorType) {
when (error) {
is ErrorType.NetworkError -> println("Network error occurred")
is ErrorType.ServerError -> println("Server error with code: ${error.code}")
is ErrorType.UnknownError -> println("Unknown error occurred")
}
}
使用密封类的优点
- 类型安全:密封类提供了类型安全性,确保所有可能的类型都被显式处理。
- 易于维护:由于密封类的子类必须在同一文件中定义,因此很容易查看和维护所有可能的子类。
- 简化 when 表达式:在 when 表达式中处理密封类时,如果遗漏了某个子类,编译器会发出警告,从而减少错误。
总结
密封类在 Kotlin 中非常适合用于表示有限的状态集或结果类型,可以提高代码的类型安全性和可维护性。在需要处理一组有限的、不变的可能状态或结果时,密封类是一个强大的工具。
4.2 声明带非默认构造方法或属性的类
class User(val email: String) //声明一个简单类
class Main(){
fun main(args: Array<String>){
//创建实例只需要调用构造方法,不需要new关键字
val alice = Users("Alice",false)
println(alice.isSub)
}
}
class Users constructor (private val _email: String, val isSub :Boolean = true){ // constructor 用于开始一个主构造方法或从构造方法的声明
val email : String = _email // init 用于引入一个初始化语句块
}
// 声明一个不带主构造方法,有从构造方法的类
open class View {
constructor(ctx :Context){
}
constructor(ctx :Context,att:AttributeSet){
}
}
class MyButton : View {
constructor(ctx :Context):this(ctx = ctx){
println()
}
constructor(ctx: Context,att: AttributeSet):super(ctx, att){
}
}