类、对象和接口

一、定义类的继承结构

一)Kotlin中的接口

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

 interface Clickable{
fun click()
fun showoff()=println("It's show time!")
} interface Focusable{
fun setFocus(b: Boolean)=
println("I ${if (b) "got" else "lost"} focus.")
fun showoff()= println("Kotlin")
} class Button: Clickable, Focusable{
//override用法同Java@Override但为强制要求
override fun click() {
println("I was clicked!")
} //这里如果没有显示地实现showoff,会得到编译错误
override fun showoff(){
//Java中的用法:Clickable.super.showoff();
/*super<Clickable>.showoff()
super<Focusable>.showoff()*/
println("Method of son.")
}
}

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

 /**
* Java中的类和方法默认是open的,而Kotlin中默认是final的。
* 如果你想允许一个类创建一个子类,需要使用open修饰符来标识这个类
* 方法与属性也是如此。
* */
open class Button: Clickable{
//这个函数是open的
override fun click() {
println("Clicking it")
}
//这个函数不再是open的了
final override fun showoff()= println("Show off")
open fun animate(){}
} /**
* abstract类与Java中的相同,不能被实例化。
*
* */
abstract class Animated{
//这个函数是抽象的,必须被子类实现,所以也是open的
abstract fun animated() //抽象类中的非抽象函数并不是默认open的,但可以标注为open的
open fun stopAnimating()= println("Stop it!")
}

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

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

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

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

 open internal class Button{
private fun click()= println("Hey!")
protected fun showoff()= println("show it")
} /*
fun Button.fMethod(){ //错误:public成员暴露了其"internal"接收者类型B
yell() //错误
showoff() //错误
}
*/ internal fun Button.fMethod(){
/*showoff() 任然错误*/
}

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

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

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

引用外部类实例语法:this@outer

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

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

请思考这样做的好处。

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

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

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

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

 //没有主构造函数
open class View{
constructor(ctx: String)
constructor(ctx: String, attr: String)
} class MyButton : View{
constructor(ctx: String) :this(ctx,"s") constructor(ctx: String,attr: String) : super(ctx,attr){
/*some code*/
}
}

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

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

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

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

五)修改访问其可见性

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

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

一)通用的对象方法

1.toString()

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

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

 class Client(val name: String,val postalCode: Int){
override fun equals(other: Any?): Boolean {
if (other==null || other !is Client) return false
return name==other.name && postalCode==other.postalCode
} override fun toString(): String {
return "Client($name,$postalCode)"
} override fun hashCode(): Int {
return name.hashCode()*12+postalCode
}
}

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

如果为类添加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()
}

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

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

  1. java面向对象基础(三):对象转型和多态

    */ .hljs { display: block; overflow-x: auto; padding: 0.5em; color: #333; background: #f8f8f8; } .hl ...

  2. JavaScript 基础(三) - Date对象,RegExp对象,Math对象,Window 对象,History 对象,Location 对象,DOM 节点

    Date对象 创建Date对象 //方法1:不指定参数 var date_obj = new Date(); alert(date_obj.toLocaleString()) //方法2:参数为日期字 ...

  3. ES6基础三(对象)

    对象赋值 在es6中,可以直接将声明的变量赋值给对象:     Object.keys().Object.values()和Object.entries() 在ES6中,允许我们使用变量作为对象的ke ...

  4. C# 开发 —— 数组类对象接口

    数组类型是从抽象基类 Array 派生的引用类型,通过new运算符创建数组并将数组元素初始化为他们的默认值 一维数组 type[] arrayname; 数组的长度不是声明的一部分,而且数组必须在访问 ...

  5. java语言基础(八)_接口_多态

    接口 1. 接口定义的基本格式 接口就是多个类的公共规范,是一种引用数据类型,最重要的内容就是其中的:抽象方法. 如何定义一个接口的格式: public interface 接口名称 { // 接口内 ...

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

    1.流的简述及演示案例输入流和输出流相对于内存设备而言.将外设中的数据读取到内存中:输入将内存的数写入到外设中:输出.字符流的由来:其实就是:字节流读取文字字节数据后,不直接操作而是先查指定的编码表. ...

  7. IOS基础之 (三) 类的声明和对象的创建

    一 OC类的声明和实现语法 1.接口的声明 @interface NewClassName: ParentClassName { 实例变量 ... } 方法的声明 ... @end //...表示省略 ...

  8. Java基础(三)对象与类

    1.类的概念:类是构造对象的模板或蓝图.由类构造对象的过程称为创建类的实例. 2.封装的概念:封装(有时称为数据隐藏)是与对象有关的一个重要概念.对象中的数据称为实例域,操纵数据的过程称为方法.对于每 ...

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

    目录 第一章 对象导论第二章 一切都是对象第三章 操作符第四章 控制执行流程第五章 初始化与清理第六章 访问权限控制第七章 复用类第九章 接口 第一章 对象导论 1. 对象的数据位于何处? 有两种方式 ...

随机推荐

  1. C++ 关于ShowWindow()的疑问

    IDE: Code::Blocks 16.01 操作系统:Windows 7 x64 最初的代码,目的是为了隐藏窗口出现在任务栏上的图标. #include <windows.h> usi ...

  2. HDU 1075 What Are You Talking About (stl之map映射)

    What Are You Talking About Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 102400/204800 K ...

  3. 在CI框架中如何实现伪静态

    第一步:在根目录下(index.PHP)同一级目录下建立一个.htaccess这个文件文件内容(即红色标识所显示的内容) URI 类 和 URL 辅助函数 包含了一些函数可以让你更容易的处理 URI ...

  4. Jmeter入门(压力测试)

    Jmeter介绍 Jmeter是一款使用Java开发的,开源免费的,测试工具, 主要用来做功能测试和性能测试(压力测试/负载测试). 而且用Jmeter 来测试 Restful API, 非常好用. ...

  5. Introduction to boundary integral equations in BEM

    Boundary element method (BEM) is an effective tool compared to finite element method (FEM) for resol ...

  6. php7安装参数编译

    系统:Centos6.8 软件包:php-7.0.14.tar.gz yum install bzip2 bzip2-devel -y yum install curl curl-devel -y y ...

  7. Nginx动静分离

    动静分离 Nginx动静分离是让动态网站里的动态网页根据一定规则把不变的资源和经常变的资源区分开来,动静资源做好了拆分以后,我们就可以根据静态资源的特点将其做缓存操作,这就是网站静态化处理的核心思路. ...

  8. device not found解决方案

    今天在使用cordova tools进行真机调试的,报了一个错:device not found; 字面意思就是没有发现设备,这时候可以首先尝试重启adb服务 C:\Users\username\Ap ...

  9. c_数据结构_顺序表

    #define OK 1 #define ERROR 0 #define OVERFLOW -2 #define LIST_INIT_SIZE 100 // 线性表存储空间的初始分配量 #define ...

  10. Python_二维数组

    例1:将数组旋转90度 a = [[i for i in range(4)] for n in range(4)] print(a) # 遍历大序列 for a_index, w in enumera ...