Kotiln类和继承
类(class)
Kotlin中,使用class关键字生命一个类。类声明由类名,类头(指定其类型参数,主构造函数等)和大括号括起来的类体组成。
class MyClass public constructor(arg1:String){
}
构造器
Kotlin中,一个类可以有一个主构造函数或和一个或多个次构造函数。主构造函数是类头的一部分,跟在类名(和可选的类型参数)后面,如果主构造函数没有任何注解或可见性修饰符,可以省略constructor关键字。
主构造函数
主构造函数不包含任何的代码,初始化代码可以放到init关键字修饰的初始化块中
主构造函数中的参数可以在初始化块,或类体内声明的属性初始化器中使用
class MyClass (arg1:String){
var str:String=arg1
//初始化块
init {
print(arg1)
}
}
第二构造函
类也可以声明前缀有constructor的次构造函数,如果类有主构造函数,每个次构造函数都要委托给主构造函数,可以直接委托,也可以通过别的次构造函数间接委托。委托到同一个类中的另一个构造函数,用this关键字即可。
class MyClass (var arg1:String){
constructor():this("")//次构造函数
}
在主构造器中可以使用var和val,但是在第二构造函函数中不能使用var和val,这就意味着第二构造函数都是只读的,不能在构造器内部改变参数的值
默认参数
Java不支持默认参数,因为JVM不支持,但是Kotlin函数支持默认参数,让我们看一个简单的例子
class MyClass (val bill:String = "Bill",var value : Float = 20.4F){
}
如果使用MyClass可以直接使用MyClass()。bill和value就会使用默认值
类成员
Kotlin中可以包含多种成员,如属性、函数、嵌套类等
属性的用法
1 . 属性的基本用法
class MyClass{
var name:String = "a"
val value :Int = 20
}
2 . 属性的getter和setter形式
// 属性的get和set函数
class Customer
{
var mValue:Int =0
// 只读属性
val name:String
get() = "Bill"
var value:Int = 0
get()
{
println("value.get")
// return mValue
return field
}
set(value:Int)
{
println("value.set")
field = value
}
}
3 . field
Kotlin为我们提供了更便捷的方式解决保存属性值得问题,field。在属性getter和setter中,可以将field当做成员变量使用,也就是通过field读写属性值
函数
在Kotlin中函数既可以在类外部定义,也可以在类内部定义。如果是前者,是全局函数,如果是后者,是类成员函数。无论函数在哪定义,语法规则基本是一样的。函数也支持默认参数值,带默认参数的必须是最后几个参数,也就是说如果某个参数带默认值,那么该参数后面所有的参数都必须有默认值
package testclass.testinterface
// 函数
// 全局函数(在类的外部定义)
// 类成员函数(在类的内部定义)
// 1. 参数的默认值
// 包含默认值的参数应该在最后
// 2. 命名参数
// 3. 可变参数,需要用vararg表示参数为可变参数
// 4. 函数的单行表达式
// 5. 嵌套函数
class QACommunity1
{
// schema参数有默认值
fun printQACommunity(url:String, schema:String="https",value:Int = 0)
{
println("${schema}://${url}")
}
}
class Person1
{
fun process(value:Int, name:String = "Bill", age:Int = 30, salary:Float = 4000F)
{
println("value:${value}, name:${name}, age:${age}, salary:${salary}")
}
}
class Persons
{
// persons为可变参数,课传入任意多个Person1对象
fun addPersons(vararg persons:Person):List<Person>
{
val result = ArrayList<Person>()
for(person in persons)
{
result.add(person)
}
return result
}
}
fun getName():String = "Bill"
/*
fun getName():String
{
return "Bill"
}
*/
fun main(args: Array<String>)
{
QACommunity1().printQACommunity("geekori.com");
//Person1().process(30,"Bill", 30, 12000F)
// 命名参数
Person1().process(30,salary = 12000F,name = "Mary")
// 可变参数
var persons = Persons().addPersons(Person("Bill"), Person("Mike"), Person("John"))
for(person in persons)
{
println(person.name)
}
// 函数的单行表达式
println(getName())
// 嵌套函数
fun process(age:Int)
{
println("age:${age}")
fun process1()
{
}
}
process(40)
嵌套类
所谓嵌套类,就是类中定义的类
// 嵌套类
class Outer
{
private val bar:Int = 20
// 嵌套类
inner class Nested
{
fun foo() = bar
}
fun process()
{
println(Nested())
}
}
嵌套类可以使用inner声明,这样可以通过外部类(包含嵌套类的类)的实例引用嵌套类
修饰符(作用域)
- public:默认,总是可见
- internal:同模块可见
- private:声明范围与同模块的子作用域可见
- protected:类似于private,但对子类也可见
继承
Kotlin中所有的类都有一个共同的超累类Any,对于没有超类型声明的类是默认超类。Any类不是java.lang.Object类,它只有equals,hashCode(),toString()3个成员方法。与Java不同,Kotlin通过“:”来继承。
open class Parent
{
protected var mName:String = "Bill"
fun getName():String {
return mName
}
}
class Child : Parent()
{
fun printName()
{
println(getName())
}
}
要显式声明一个超类,可以把类型放到类头的冒号之后,如果该基类有一个主构造函数,则其基类必须用主构造函数的参数就地初始化:
class B constructor(arg: String):A(arg){
}
- 在kotlin中,不仅类默认是不可继承的,连方法默认也是不可重写的。因此,如果要在子类中重写方法,就需要在父类相应的方法前面加open关键字,而且要在子类重写的方法前面加override关键字。
- 在kotlin中,val属性可以被重写为var属性,但反过来不可以
open class Parent
{
protected var mName:String = "Bill"
open fun function()
{
}
open val name:String = "Mary"
get()
{
println("获取Parent.name属性值")
return field
}
}
class Child : Parent()
{
fun printName()
{
println(mName)
}
override var name: String = "Mike"
get()
{
println("获取Child.name属性")
return field
}
set(value)
{
field = value
println("Child.name被写入")
}
}
接口
- 在kotlin中接口与Java雷士,使用interface关键字声明。一个类可以实现多个接口,实现的方法和类继承相同。而且接口中的属性和方法都是open的。
- 在kotlin中,允许接口的方法包含默认的方法体。对于有方法体的接口方法,并不要求一定重写该方法。
// 对象和委托:对象表达式
// Kotlin中的对象是为了代替Java中的匿名类
open class KotlinClass(name:String)
{
open var name = name
open fun verify()
{
println("verify")
}
}
interface MyInterface
{
fun closeData()
{
println("closeData")
}
}
fun process(obj:KotlinClass)
{
obj.verify()
if(obj is MyInterface)
{
obj.closeData()
}
}
fun main(args: Array<String>)
{
process(object :KotlinClass("John"),MyInterface{
override fun verify() {
println("object verify")
}
});
// 直接建立对象
fun foo()
{
val obj = object
{
var x:Int = 10
var y:Int = 20
}
println(obj.x + obj.y)
}
foo()
}