Kotlin基础(三)类、对象和接口
类、对象和接口
一、定义类的继承结构
一)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基础(三)类、对象和接口的更多相关文章
- java面向对象基础(三):对象转型和多态
*/ .hljs { display: block; overflow-x: auto; padding: 0.5em; color: #333; background: #f8f8f8; } .hl ...
- JavaScript 基础(三) - Date对象,RegExp对象,Math对象,Window 对象,History 对象,Location 对象,DOM 节点
Date对象 创建Date对象 //方法1:不指定参数 var date_obj = new Date(); alert(date_obj.toLocaleString()) //方法2:参数为日期字 ...
- ES6基础三(对象)
对象赋值 在es6中,可以直接将声明的变量赋值给对象: Object.keys().Object.values()和Object.entries() 在ES6中,允许我们使用变量作为对象的ke ...
- C# 开发 —— 数组类对象接口
数组类型是从抽象基类 Array 派生的引用类型,通过new运算符创建数组并将数组元素初始化为他们的默认值 一维数组 type[] arrayname; 数组的长度不是声明的一部分,而且数组必须在访问 ...
- java语言基础(八)_接口_多态
接口 1. 接口定义的基本格式 接口就是多个类的公共规范,是一种引用数据类型,最重要的内容就是其中的:抽象方法. 如何定义一个接口的格式: public interface 接口名称 { // 接口内 ...
- JAVA基础学习之流的简述及演示案例、用缓冲区方法buffer读写文件、File类对象的使用、Serializable标记接口(6)
1.流的简述及演示案例输入流和输出流相对于内存设备而言.将外设中的数据读取到内存中:输入将内存的数写入到外设中:输出.字符流的由来:其实就是:字节流读取文字字节数据后,不直接操作而是先查指定的编码表. ...
- IOS基础之 (三) 类的声明和对象的创建
一 OC类的声明和实现语法 1.接口的声明 @interface NewClassName: ParentClassName { 实例变量 ... } 方法的声明 ... @end //...表示省略 ...
- Java基础(三)对象与类
1.类的概念:类是构造对象的模板或蓝图.由类构造对象的过程称为创建类的实例. 2.封装的概念:封装(有时称为数据隐藏)是与对象有关的一个重要概念.对象中的数据称为实例域,操纵数据的过程称为方法.对于每 ...
- [Think In Java]基础拾遗1 - 对象初始化、垃圾回收器、继承、组合、代理、接口、抽象类
目录 第一章 对象导论第二章 一切都是对象第三章 操作符第四章 控制执行流程第五章 初始化与清理第六章 访问权限控制第七章 复用类第九章 接口 第一章 对象导论 1. 对象的数据位于何处? 有两种方式 ...
随机推荐
- MySQL5.7.20安装过程报错CMake Error at cmake/boost.cmake:81 (MESSAGE):
MySQL在5.7版本及以后,都需要boots 库,所以需要先安装boots 步骤: 1.在/usr/local下创建 名为boots的目录 mkdir -p /usr/local/boots 2.进 ...
- python unittest套件,修改为失败重新执行
#套件,修改为失败重新执行 import time import unittest from unittest.suite import _isnotsuite class Suit(unittest ...
- mysql 语句的使用清库数据转移
mysql清空数据库表 方法1:重建库和表用mysqldump --no-data把建表SQL导出来,然后drop database再create database,执行一下导出的SQL文件: 方法2 ...
- docker文件复制到centos/linux/ubantun环境下
1.有些时候我们需要将容器里面的文件,弄到系统里面来分析,像报错log等 格式:docker cp 容器名:文件在容器里面的路径 要拷贝到宿主机的对应路径 2.有些情况下,我们需要将文 ...
- JAVA之复制数组
//复制数组 //Arrays.copyOf(arr, 5) //arr:要复制的对象,5为新数组的长度 import java.util.Arrays; public class Cope { pu ...
- 浅拷贝和深拷贝(谈谈java中的clone)
clone顾名思义就是复制, 在Java语言中, clone方法被对象调用,所以会复制对象.所谓的复制对象,首先要分配一个和源对象同样大小的空间,在这个空间中创建一个新的对象.那么在java语言中,有 ...
- innobackupex做MySQL增量备份及恢复
http://www.cnblogs.com/paul8339/p/6731688.html
- SpringBank 开发日志 使用maven构建dubbo服务的可执行jar包
写这篇日志的时候,我已经完成了这个目标,并且中间经历了一次面试.现在回过头看,已经觉得印象不那么深刻了,果然还是一边思考,一边记录这样最好.但我还是严格要求自己,从新做了梳理,对相关配置进行了整理和说 ...
- [转] Webpack 打包优化之体积篇
谈及如今欣欣向荣的前端圈,不仅有各类框架百花齐放,如Vue, React, Angular等等,就打包工具而言,发展也是如火如荼,百家争鸣:从早期的王者Browserify, Grunt,到后来赢得宝 ...
- Temporal Segment Networks
摘要 解决问题 用CNN框架有效提取video长时序特征 在UCF101等训练集受限的情况下训练网络 贡献 TSN网络,基于长时间时序结构模型.稀疏时序采样策略,视频层监督有效学习整个视频. HMDB ...