学习kotlin第八天_接口、可见性修饰符、扩展
2017-06-01 14:50
477 查看
暂时跳过昨天那几个坑,继续跟着官方文档懵逼。
坑1、使用interface定义接口,与java8类似,可以有抽象方法的声明,也可以有实现。
interface
MyInterface {
fun
bar()
fun
foo() {
// 可选的方法体
}
}
悲剧了,java8不熟悉,又来恶补一下。
1、java8之前,接口中只能有全局静态常量和全局抽象方法。java8中允许有方法的实现,即默认方法,用default修饰。(类似地,已经有Connection集合,同时又有Connections工具类并且Connections中均为操作集合的方法,因此应该全放入Connection中)
public interface
MyIF {
default
String getName() {
return
"小猴子";
}
}
2、类优先原则。(1)、若一个接口中定义了一个默认方法,而另外一个父类中又定义了一个同名的方法时,接口中同名同参的默认方法会被忽略。(2)两接口方法冲突时子类会报错,需要在子类中重写该方法,并调用“接口名.super.方法”。
3、Java8接口中可以有静态方法,调用方法为“接口名.方法”
言归正传,回到kotlin。
Kotlin接口与抽象类不同的是接口无法保存状态。。。没懂,求解释!
坑2、它可以有属性但必须声明为抽象或提供
4000
访问器实现。在接口中声明的属性不能有幕后字段。。。自始至终就没懂幕后字段是啥
interface
MyInterface {
abstract
val prop:
Int // 抽象的,这里可以省略abstract关键字
val
propertyWithImplementation:
String
get()
= "foo"
fun
foo() {
print(prop)
}
}
class
Child : MyInterface {
override
val prop:
Int = 29
}
坑3、类似与java8,接口冲突时需要在子类中重写该方法,并调用“super<接口名>.方法名”
坑4、kotlin中有四个可见性修饰符,默认为public。类、对象、接口、构造函数、方法、属性和它们的
setter
都可以有可见性修饰符。
(1)函数、属性和类、对象和接口可以在顶层声明,即直接在包内:
如果你不指定任何可见性修饰符,默认为 public ,这意味着你的声明 将随处可见;
如果你声明为 private ,它只会在声明它的文件内可见;
如果你声明为 internal ,它会在相同模块内随处可见;
protected 不适用于顶层声明。
// 文件名:example.kt
package
foo
private fun
foo() {}
// 在 example.kt 内可见
public var
bar:
Int = 5
// 该属性随处可见
private
set // setter 只在 example.kt 内可见
internal val
baz
=
6
// 相同模块内可见
(2)对于类内部声明的成员:
private ——意味着只在当前类内部(包含其所有成员)可见;
protected ——在类中及其子类中可见。
internal —— 能见到类声明的本模块内的任何客户端都可见其 internal 成员;
public —— 能见到类声明的任何客户端都可见其 public 成员。
open class
Outer {
private
val a
=
1
protected
open val b
=
2
internal
val c
=
3
val
d
=
4
// 默认 public
protected
class Nested {
public
val e:
Int = 5
}
}
class
Subclass : Outer() {
//
a 不可见
// b、c、d 可见
// Nested 和 e 可见
override
val b
=
5
// “b”为 protected
}
class
Unrelated(o: Outer) {
// o.a、o.b 不可见
// o.c 和 o.d 可见(相同模块)
// Outer.Nested 不可见,Nested::e 也不可见
}
坑5、构造函数的可见性必须有显示的constructor关键字。并在前加修饰符。默认情况下为public类型,故取决于类的可见性。
坑6、局部变量、函数和类不能有可见性修饰符。瞬间懵逼了,前面不还说“类和方法可以有可见性修饰符”?因为这里强调的是局部。。。通俗地说是函数中的局部变量、函数和类不能有可见性修饰符。。。原来函数中还能包含函数,醉了。
坑7、前面提到了internal表示模块内可见,那模块是啥呢,模块是编译在一起的一套kotlin文件:
一个 IntelliJ IDEA 模块;
一个 Maven 或者 Gradle 项目;
一次
<kotlinc> Ant 任务执行所编译的一套文件。
其实我仍然没懂模块是啥。。。
坑8、kotlin支持扩展函数和扩展属性,用于扩展一个类的功能而无需继承或使用类似装饰者模式类似的设计模式。
例如给MutableList<Int>添加swap函数
fun
MutableList<Int>.swap(index1: Int, index2: Int) {
val
tmp =
this[index1]
// “this”对应该列表
this[index1]
= this[index2]
this[index2]
= tmp
}
fun
main(args: Array<String>) {
val
l =
mutableListOf(1,
2,
3,
4)
l.swap(1,
3)
l.forEach
{
println(it)
}
}
当然,该方法也可以被泛化。为了在接收者类型表达式中使用泛型,需要在函数名前面声明泛型参数。。。没懂,照葫芦画瓢吧。。。
fun
<T> MutableList<T>.swap(index1: Int, index2: Int) {
val
tmp =
this[index1]
// “this”对应该列表
this[index1]
= this[index2]
this[index2]
= tmp
}
坑9、扩展函数是静态分发的。如下,调用的扩展函数只取决于参数声明的类型
open class
C
class
D: C()
fun
C.foo() =
"c"
fun
D.foo() =
"d"
fun
printFoo(c:C) {
println(c.foo())
}
fun
main(args: Array<String>) {
printFoo(D())
}
成员函数和扩展函数冲突(函数名和参数均一致)时,取成员函数。
class
C {
fun
foo() {
println("member")
}
}
fun
C.foo() {
println("extension")
}
为可空接收者类型定义扩展:
坑10、扩展属性不能有初始化器,他们的行为只能由显式提供的getter是/setters定义。
val
<T>
List<T>.lastIndex:
Int
get()
= size
-
1
坑11、伴生对象也能定义扩展函数和属性,伴生对象是啥?。。。后面慢慢了解。
坑12、我们通常直接在包里定义扩展,如果需要使用包外的扩展,需要导入包。
坑13、扩展声明为成员这个又没看懂,悲剧了。。。
今天就到此为止吧。。。
坑1、使用interface定义接口,与java8类似,可以有抽象方法的声明,也可以有实现。
interface
MyInterface {
fun
bar()
fun
foo() {
// 可选的方法体
}
}
悲剧了,java8不熟悉,又来恶补一下。
1、java8之前,接口中只能有全局静态常量和全局抽象方法。java8中允许有方法的实现,即默认方法,用default修饰。(类似地,已经有Connection集合,同时又有Connections工具类并且Connections中均为操作集合的方法,因此应该全放入Connection中)
public interface
MyIF {
default
String getName() {
return
"小猴子";
}
}
2、类优先原则。(1)、若一个接口中定义了一个默认方法,而另外一个父类中又定义了一个同名的方法时,接口中同名同参的默认方法会被忽略。(2)两接口方法冲突时子类会报错,需要在子类中重写该方法,并调用“接口名.super.方法”。
3、Java8接口中可以有静态方法,调用方法为“接口名.方法”
言归正传,回到kotlin。
Kotlin接口与抽象类不同的是接口无法保存状态。。。没懂,求解释!
坑2、它可以有属性但必须声明为抽象或提供
4000
访问器实现。在接口中声明的属性不能有幕后字段。。。自始至终就没懂幕后字段是啥
interface
MyInterface {
abstract
val prop:
Int // 抽象的,这里可以省略abstract关键字
val
propertyWithImplementation:
String
get()
= "foo"
fun
foo() {
print(prop)
}
}
class
Child : MyInterface {
override
val prop:
Int = 29
}
坑3、类似与java8,接口冲突时需要在子类中重写该方法,并调用“super<接口名>.方法名”
坑4、kotlin中有四个可见性修饰符,默认为public。类、对象、接口、构造函数、方法、属性和它们的
setter
都可以有可见性修饰符。
(1)函数、属性和类、对象和接口可以在顶层声明,即直接在包内:
如果你不指定任何可见性修饰符,默认为 public ,这意味着你的声明 将随处可见;
如果你声明为 private ,它只会在声明它的文件内可见;
如果你声明为 internal ,它会在相同模块内随处可见;
protected 不适用于顶层声明。
// 文件名:example.kt
package
foo
private fun
foo() {}
// 在 example.kt 内可见
public var
bar:
Int = 5
// 该属性随处可见
private
set // setter 只在 example.kt 内可见
internal val
baz
=
6
// 相同模块内可见
(2)对于类内部声明的成员:
private ——意味着只在当前类内部(包含其所有成员)可见;
protected ——在类中及其子类中可见。
internal —— 能见到类声明的本模块内的任何客户端都可见其 internal 成员;
public —— 能见到类声明的任何客户端都可见其 public 成员。
open class
Outer {
private
val a
=
1
protected
open val b
=
2
internal
val c
=
3
val
d
=
4
// 默认 public
protected
class Nested {
public
val e:
Int = 5
}
}
class
Subclass : Outer() {
//
a 不可见
// b、c、d 可见
// Nested 和 e 可见
override
val b
=
5
// “b”为 protected
}
class
Unrelated(o: Outer) {
// o.a、o.b 不可见
// o.c 和 o.d 可见(相同模块)
// Outer.Nested 不可见,Nested::e 也不可见
}
坑5、构造函数的可见性必须有显示的constructor关键字。并在前加修饰符。默认情况下为public类型,故取决于类的可见性。
坑6、局部变量、函数和类不能有可见性修饰符。瞬间懵逼了,前面不还说“类和方法可以有可见性修饰符”?因为这里强调的是局部。。。通俗地说是函数中的局部变量、函数和类不能有可见性修饰符。。。原来函数中还能包含函数,醉了。
坑7、前面提到了internal表示模块内可见,那模块是啥呢,模块是编译在一起的一套kotlin文件:
一个 IntelliJ IDEA 模块;
一个 Maven 或者 Gradle 项目;
一次
<kotlinc> Ant 任务执行所编译的一套文件。
其实我仍然没懂模块是啥。。。
坑8、kotlin支持扩展函数和扩展属性,用于扩展一个类的功能而无需继承或使用类似装饰者模式类似的设计模式。
例如给MutableList<Int>添加swap函数
fun
MutableList<Int>.swap(index1: Int, index2: Int) {
val
tmp =
this[index1]
// “this”对应该列表
this[index1]
= this[index2]
this[index2]
= tmp
}
fun
main(args: Array<String>) {
val
l =
mutableListOf(1,
2,
3,
4)
l.swap(1,
3)
l.forEach
{
println(it)
}
}
当然,该方法也可以被泛化。为了在接收者类型表达式中使用泛型,需要在函数名前面声明泛型参数。。。没懂,照葫芦画瓢吧。。。
fun
<T> MutableList<T>.swap(index1: Int, index2: Int) {
val
tmp =
this[index1]
// “this”对应该列表
this[index1]
= this[index2]
this[index2]
= tmp
}
坑9、扩展函数是静态分发的。如下,调用的扩展函数只取决于参数声明的类型
open class
C
class
D: C()
fun
C.foo() =
"c"
fun
D.foo() =
"d"
fun
printFoo(c:C) {
println(c.foo())
}
fun
main(args: Array<String>) {
printFoo(D())
}
成员函数和扩展函数冲突(函数名和参数均一致)时,取成员函数。
class
C {
fun
foo() {
println("member")
}
}
fun
C.foo() {
println("extension")
}
为可空接收者类型定义扩展:
坑10、扩展属性不能有初始化器,他们的行为只能由显式提供的getter是/setters定义。
val
<T>
List<T>.lastIndex:
Int
get()
= size
-
1
坑11、伴生对象也能定义扩展函数和属性,伴生对象是啥?。。。后面慢慢了解。
坑12、我们通常直接在包里定义扩展,如果需要使用包外的扩展,需要导入包。
坑13、扩展声明为成员这个又没看懂,悲剧了。。。
今天就到此为止吧。。。
相关文章推荐
- Kotlin学习(四)—— 类和对象,继承,覆盖,抽象类,属性和字段,接口,可见性修饰符,扩展
- Kotlin学习(四)—— 类和对象,继承,覆盖,抽象类,属性和字段,接口,可见性修饰符,扩展
- Kotlin 官方学习教程之可见性修饰符
- Kotlin学习(十): 可见性修饰符和数据类
- Kotlin 学习之可见性修饰符
- Kotlin学习(11):可见性修饰符
- Kotlin 从学习到 Android 第九章 可见性修饰符
- Kotlin汇总3-接口,可见作用域,扩展,数据类,密封类
- Kotlin 官方学习教程之接口
- Kotlin教程学习-dataclass,objectclass,use函数,类扩展,socket
- 0307学习接口:扩展
- C#基础:通过一个实例来学习IFormattable接口,扩展方法
- Android开发,Kotlin的了解与学习(七)-----接口与实现
- C#基础:通过一个实例来学习IFormattable接口,扩展方法
- Kotlin 可见性修饰符
- Kotlin学习笔记(五)接口,可见性修饰符
- Kotlin学习之-5.3 接口
- Kotlin 官方学习教程之扩展
- shell学习第八天----扩展正则表达式(ERE)
- java 学习 私有类实现接口 ,一个类继承来的方法和接口实现方法重复第八天