Kotlin基础(三)类、对象和接口

类、对象和接口

一、定义类的继承结构

一)Kotlin中的接口

Kotlin的接口与Java8中相似,它们可以包含抽象方法的定义以及非抽象方法的实现,但它们不能包含任何状态。

 1 interface Clickable{
 2     fun click()
 3     fun showoff()=println("It‘s show time!")
 4 }
 5
 6 interface Focusable{
 7     fun setFocus(b: Boolean)=
 8             println("I ${if (b) "got" else "lost"} focus.")
 9     fun showoff()= println("Kotlin")
10 }
11
12 class Button: Clickable, Focusable{
13     //override用法同[email protected]但为强制要求
14     override fun click() {
15         println("I was clicked!")
16     }
17
18     //这里如果没有显示地实现showoff,会得到编译错误
19     override fun showoff(){
20         //Java中的用法:Clickable.super.showoff();
21         /*super<Clickable>.showoff()
22         super<Focusable>.showoff()*/
23         println("Method of son.")
24     }
25 }

二)控制继承的修饰符:open、final和abstract:默认为final

 1 /**
 2 * Java中的类和方法默认是open的,而Kotlin中默认是final的。
 3 * 如果你想允许一个类创建一个子类,需要使用open修饰符来标识这个类
 4 * 方法与属性也是如此。
 5 * */
 6 open class Button: Clickable{
 7     //这个函数是open的
 8     override fun click() {
 9         println("Clicking it")
10     }
11     //这个函数不再是open的了
12     final override fun showoff()= println("Show off")
13     open fun animate(){}
14 }
15
16 /**
17 * abstract类与Java中的相同,不能被实例化。
18 *
19 * */
20 abstract class Animated{
21     //这个函数是抽象的,必须被子类实现,所以也是open的
22     abstract fun animated()
23
24     //抽象类中的非抽象函数并不是默认open的,但可以标注为open的
25     open fun stopAnimating()= println("Stop it!")
26 }

三)可见性修饰符:public,protected,internal和private,默认为public

可见性修饰符帮助控制对代码库中声明的访问。Java中默认可见性为-----包私有,在Kotlin只把包作为在命名空间里组织代码的一种方式使用,并没有将其用作可见性控制。

作为替代Kotlin中提供了一种新的修饰符---internal,表示"只在模块(一组一起编译的Kotlin文件)内部可见"。另外一个区别就是Kotlin允许在顶层声明中使用private可见性,

使这些声明只会在声明他们的文件中可见。

 1 open internal class Button{
 2     private fun click()= println("Hey!")
 3     protected fun showoff()= println("show it")
 4 }
 5
 6 /*
 7 fun Button.fMethod(){ //错误:public成员暴露了其"internal"接收者类型B
 8     yell() //错误
 9     showoff() //错误
10 }
11 */
12
13 internal fun Button.fMethod(){
14     /*showoff()  任然错误*/
15 }

另一个与Java可见性不同的是:一个外部类不能看到其内部类或嵌套类中的private成员。

四)内部类和嵌套类:默认为嵌套类

只需要记住Kotlin中没有显示修饰符的嵌套类与Java中的static嵌套类是一样的,如果要使其持有外部类的引用的话需要使用inner修饰符。

引用外部类实例语法:[email protected]

五)密封类:定义受限的类继承结构

为父类添加一个sealed修饰符,对可能创建的子类做出严格限制,所有的直接子类必须嵌套在父类中。

请思考这样做的好处。

二、声明一个带默认构造方法或属性的类

一)初始化类:主构造方法和初始化语句块

 1 class User0(val name: String="tang"/*可提供默认值*/) /*简便写法,其中val关键字意味着
 2 相应的属性会用构造方法的参数来初始化*/
 3
 4 open class User constructor(name: String)/*带参数的主构造方法,constructor
 5     用来声明一个主构造方法和一个从构造方法*/{
 6     val name:String
 7
 8     init { //初始化语句块,因为主构造方法的语法限制,所有有了初始化语句
 9         //一个类中可以声明多个初始化语句
10         this.name=name
11     }
12 }
13
14 //如果一个类具有父类,主构造方法同样需要初始化父类。
15 // 即使父类构造函数没有任何参数,也要显示地调用构造函数。
16 class TwitterUser(name: String) : User(name){}
17
18 //如果要确保类不被实例化,可以把构造函数标记为private
19 class Person private constructor(val name: String)

二)构造方法:用不同的方法来初始化父类

 1 //没有主构造函数
 2 open class View{
 3     constructor(ctx: String)
 4     constructor(ctx: String, attr: String)
 5 }
 6
 7 class MyButton : View{
 8     constructor(ctx: String) :this(ctx,"s")
 9
10     constructor(ctx: String,attr: String) : super(ctx,attr){
11         /*some code*/
12     }
13 }

三)实现在接口中声明的属性

 1 /*接口可以包含抽象属性声明*/
 2 interface User{
 3     val nickname: String
 4     /*接口还可包含具有getter和setter的属性,只要他们没有引用一个支持字段*/
 5     val age: Int
 6         get() = Random().nextInt(100)
 7 }
 8
 9 /*在实现了接口的类中必须override该属性*/
10 class QQUser (override val nickname: String) : User
11
12 class BaiduUser(val email: String) : User{
13     override val nickname: String
14         get() = "Baidu $email"
15 }

四)通过getter或setter访问支持字段

 1 class User(val name: String){
 2     var address: String="unspecified"
 3         //在set函数体中,使用了标识符field来访问支持字段的值。
 4         //在get函数中只能读取它,在set函数中可以修改它。
 5         set(value: String) {
 6             println("""
 7                 Address was changed for $name: "$field" -> "$value".""".trimIndent())
 8         }
 9 }
10
11 fun main(args: Array<String>) {
12     val user=User("Tom")
13     user.address="Back Street 221"
14     user.address="Beijing hu tong 222"
15     /*Address was changed for Tom: "unspecified" -> "Back Street 221".
16       Address was changed for Tom: "unspecified" -> "Beijing hu tong 222".*/
17
18 }

五)修改访问其可见性

1 class LengthCounter{
2     var counter: Int=0
3         private set //声明为private,不能再类外部修改这个属性
4
5     fun addWord(word: String){
6         counter+=word.length
7     }
8 }

三、编译器生成的方法:数据类和类委托

一)通用的对象方法

1.toString()

2.equals():在Kotlin中"=="相当于Java中的equals,"==="相当于Java中的"=="(比较引用)

3.hashCode()方法通常与equals方法一起被重写(如果两个对象相等,它们通常必须有相同的hash值)。

 1 class Client(val name: String,val postalCode: Int){
 2     override fun equals(other: Any?): Boolean {
 3         if (other==null || other !is Client) return false
 4         return name==other.name && postalCode==other.postalCode
 5     }
 6
 7     override fun toString(): String {
 8         return "Client($name,$postalCode)"
 9     }
10
11     override fun hashCode(): Int {
12         return name.hashCode()*12+postalCode
13     }
14 }

二)数据类:自动生成通用方法实现

如果为类添加data修饰符,上述通用方法将会被自动生成好。其中

1.equals方法:检测所以主构造函数属性的值是否相等。

2.hashCode方法:返回一个根据所有主构造函数中属性值生成的哈希值。

注意:没有在主构造函数中声明的属性将不会加入到相等性检测和哈希值计算中去。

data class User(val name: String,val age:Int,val gender: String)

三)类委托:使用"by"关键字

class TangCollection<T>(
        val innerList: Collection<T> = ArrayList<T>()
) : Collection<T> by innerList {}

四)"object"关键字:将声明一个类与创建一个实例结合起来

object关键字:定义一个类的同时创建一个实例

一)对象声明:创建单例

/*
* 在定义的时候就被创建,并且为一个单例
* */
object User {
    val name: String = "Tang"
    val age: Int = 8
}

二)伴生对象:工厂方法和静态成员的地盘

class A {
    companion object {
        fun t(){
            println("Tang")
        }
    }
}

fun main(args: Array<String>) {
    A.t()
}

三)作为普通对象使用的伴生对象

时间: 2024-08-29 04:34:51

Kotlin基础(三)类、对象和接口的相关文章

Kotlin基础-数据类

/* * 数据类:专用于只"保存"数据的类,比如用户自动登录信息,聊天记录等 * 这里的保存并不是指保存到磁盘,而是指转换成文本格式,便于保存 * Kotlin数据类:data class 类名(属性列表) * * */ data class Article(var id:Int,var title:String,var content:String) fun main(args: Array<String>) { val artical=Article(1001,&quo

黑马程序员---java基础-Java类 继承&amp;抽象&amp;接口

------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 一.继承 继承是所有OOP语言不可缺少的部分,在java中使用extends关键字来表示继承关系.当创建一个类时,总是在继承,如果没有明确指出要继承的类,就总是隐式地从根类Object进行继承.比如下面这段代码: 1 class Person { 2 public Person() { 3 4 } 5 } 6 class Man extends Person { 7 public Man()

【python基础】类&amp;对象

一.类 1.对同一类事物抽象的描述,抽象的概念 2.定义类的语法: class 关键字——命名规则:大驼峰StudentInfo; (小驼峰studentInfo) class 类名: pass 3.属性: 理解为用于描述类名词 (名字, 年龄, 颜色, 身高,...) 4.方法: 也叫做函数, 理解为类能够实现的行为功能(吃饭, 睡觉, 打豆豆,...) 二.对象: 真实存在的,类的具体的一个实例 1.对象 : 也叫做实例 2.创建对象的过程:叫做类的实例化 3.对象.方法() 获取对象的属性

Kotlin基础-枚举类

/* * 枚举类:有限个类型的列举 * 其中的每一个称为枚举常量(可带初值),每一个以逗号分隔 * * * */ //扑克牌花色 enum class PoKerCard{ 红心,方片,梅花,黑桃 } //衣服尺码:带构造器的枚举 enum class Size(val height:Int){ S(150),M(160),L(170) } fun main(args: Array<String>) { //列举枚举类中的常量 println(PoKerCard.values().joinTo

C# 开发 &mdash;&mdash; 数组类对象接口

数组类型是从抽象基类 Array 派生的引用类型,通过new运算符创建数组并将数组元素初始化为他们的默认值 一维数组 type[] arrayname; 数组的长度不是声明的一部分,而且数组必须在访问前初始化. foreach 语句声明一个迭代变量 -- 是数组的每个元素的只读副本 二维数组 type[,]  arrayName; int[,] arr = new int[2,2]{{1,2},{3,4}}; 可使用数组的Rank属性和GetUpperBound方法获取数组的行数和列数,然后遍历

JAVA基础学习之流的简述及演示案例、用缓冲区方法buffer读写文件、File类对象的使用、Serializable标记接口(6)

1.流的简述及演示案例输入流和输出流相对于内存设备而言.将外设中的数据读取到内存中:输入将内存的数写入到外设中:输出.字符流的由来:其实就是:字节流读取文字字节数据后,不直接操作而是先查指定的编码表.获取对应的文字.在对这个文字进行操作.简单说:字节流+编码表字节流的两个顶层父类:1,InputStream 2,OutputStream.字符流的两个顶层父类:1,Reader 2,Writer String filePath = "F:\\demo.txt"; FileWriter f

Servlet基础之一:Servlet基本接口与类

1.概述 Servlet API中共有5个包,约113个接口和类: javax.servlet javax.servlet.http javax.servlet.jsp javax.servlet.annotation javax.servlet.descriptor 2.Servlet接口 (1)所有Servlet/JSP应用必须直接或者间接实现Servlet接口, Servlet/JSP容器会将实现了Servlet接口的类加载至容器,以供访问. (2)Servlet中共定义了5个方法: vo

第四章(类、对象和接口)

Kotlin的类和接口与Java的类和接口还是有一点区别的.例如:接口可以包含属性声明.与Java不同,Kotlin的声明默认是 final?和 public?的.此外,嵌套的类默认并不是内部类:它们并没有包含对其外部类的隐式引用. Kotlin中的接口 Kotlin的接口与Java 8中的相似:它们可以包含抽象方法的定义以及非抽象方法的实现.与Java 8不同的是,Java 8中需要你在这样的实现上标注default关键字,而Kotlin没有特殊的注解:只需要提供一个方法体.示例: inter

[Think In Java]基础拾遗1 - 对象初始化、垃圾回收器、继承、组合、代理、接口、抽象类

目录 第一章 对象导论第二章 一切都是对象第三章 操作符第四章 控制执行流程第五章 初始化与清理第六章 访问权限控制第七章 复用类第九章 接口 第一章 对象导论 1. 对象的数据位于何处? 有两种方式在内存中存放对象: (1)为了追求最大的执行速度,对象的存储空间和生命周期可以在编写程序时确定,这可以通过将对象置于堆栈或者静态存储区域内来实现.这种方式牺牲了灵活性. (2)在被称为堆的内存池中动态地创建对象.在这种方式,知道运行时才知道对象需要多少对象,它们的生命周期如何,以及它们的具体类型.