回到目錄
項(xiàng)目源碼 kotlin-class 項(xiàng)目
應(yīng)該多用組合, 而不要無腦繼承. Favor composition over inheritance
為什么? 因?yàn)槭褂美^承后, 比如 B 繼承 A, 那么 B 跟 A 之間的關(guān)系就定死了, 是"is a"
的關(guān)系. 而使用組合則更靈活, B 可以委托 A, 也可以委托 A 的子類, 只要是 A 類型的就
可以了. 看下面的 java 例子:
建立委托關(guān)系, 經(jīng)理委托司機(jī)開車
public class DelegateDemo1 {
public static void main(String[] args) {
Driver d = new Driver();
Manager m = new Manager(d);
m.drive(); // 會(huì)輸出 Driver driving
}
}
class Driver {
public void drive() {
System.out.println("Driver driving");
}
}
class Manager {
private Driver driver; // 建立委托關(guān)系
Manager(Driver driver) {
this.driver = driver;
}
public void drive() {
driver.drive(); // 經(jīng)理委托司機(jī)開車
}
}
經(jīng)理對(duì)這位司機(jī)不滿意, 還可以委托老司機(jī)開車:
class OlderDriver extends Driver {
@Override
public void drive() {
System.out.println("老司機(jī)開車...");
}
}
public class DelegateDemo1 {
public static void main(String[] args) {
// Driver d = new Driver();
// Manager m = new Manager(d);
Driver old = new OlderDriver();
Manager m = new Manager(old);
m.drive();
}
}
這時(shí)候輸出的是 老司機(jī)開車...
使用接口方式的委托模式是同理的:
public class DelegateDemo1 {
public static void main(String[] args) {
new D(new B()).say(); // 打印 B says ...
new D(new C()).say(); // 打印 C says ...
}
}
interface Ia {
void say();
}
class B implements Ia {
@Override
public void say() {
System.out.println("B says ...");
}
}
class C implements Ia {
@Override
public void say() {
System.out.println("C says ...");
}
}
class D implements Ia {
private Ia delegator; // 建立委托關(guān)系
D(Ia ia) {
this.delegator = ia;
}
@Override
public void say() {
delegator.say();
}
}
Kotlin 中為了限制你使用繼承, class 都默認(rèn)是 final
的, 懂了吧.
Java 中委托模式(代理模式) 就是應(yīng)用了組合的思想.
Kotlin 從語言層面實(shí)現(xiàn)了"委托", 使用 by
關(guān)鍵字即可. 委托也可以用于屬性, 但是這
節(jié)我們只講"類委托". 上面的代碼用 Kotlin 重寫的話是這樣的:
interface Drivable {
fun drive()
}
class Driver: Drivable {
override fun drive() = println("Driver driving ...")
}
class OlderDriver: Drivable {
override fun drive() {
println("老司機(jī)開車...")
}
}
class Manager(driver: Drivable): Drivable by driver
fun main(args: Array<String>) {
Manager(Driver()).drive() // Driver driving ...
Manager(OlderDriver()).drive() // 老司機(jī)開車...
}
Kotlin 中使用只有接口才能用 by
代理, 所以我們寫了一個(gè) Drivable
接口.
對(duì)于 Manager
類來說, driver: Drivable
是代理字段, Kotlin 會(huì)自動(dòng)生成一個(gè)代理
字段(類似 $$delegate_0
). 所以寫 var
val
是無意義的. 當(dāng)然, 寫上也沒問題,
這樣會(huì)生成 driver
backing field 以及 getter setter 方法.
Manager
反編譯為 Java 代碼后的樣子:
public final class Manager implements Drivable {
// $FF: synthetic field
private final Drivable $$delegate_0;
public Manager(@NotNull Drivable driver) {
Intrinsics.checkParameterIsNotNull(driver, "driver");
super();
this.$$delegate_0 = driver;
}
public void drive() {
this.$$delegate_0.drive();
}
}
使用多個(gè) by
也是可以的:
interface Nameable {
var name: String
}
class JackName : Nameable {
override var name: String = "Jack"
}
class LongDistanceRunner: Runnable {
override fun run() {
println("long")
}
}
class Person(name: Nameable, runner: Runnable): Nameable by name, Runnable by runner
fun main(args: Array<String>) {
val person = Person(JackName(), LongDistanceRunner())
println(person.name) //Jack
person.run() //long
}