Java和Kotlin中委托的比较

Java和Kotlin中委托的比较,java,kotlin,inheritance,delegates,delegation,Java,Kotlin,Inheritance,Delegates,Delegation,我试图理解继承与委派之争,以及如何实现这两者。 我的问题是,为什么我要用by关键字实现Kotlin?我认为这太过分了 让我给你举个例子。我们有一个可以点菜的应用程序。该应用程序名为DeliveryQueen 以下是Java示例: public interface FoodDeliverable { void deliverSomeFood(); } public class PizzaCastle implements FoodDeliverable { @Override

我试图理解继承与委派之争,以及如何实现这两者。 我的问题是,为什么我要用by关键字实现Kotlin?我认为这太过分了

让我给你举个例子。我们有一个可以点菜的应用程序。该应用程序名为DeliveryQueen

以下是Java示例:

public interface FoodDeliverable {
    void deliverSomeFood();
}

public class PizzaCastle implements FoodDeliverable {
    @Override
    public void deliverSomeFood() {
        System.out.println("deliver the tastiest pizza in the world");
    }
}

public class BurgerCastle implements FoodDeliverable {
    @Override
    public void deliverSomeFood() {
        System.out.println("deliver the tastiest burger in the world");
    }
}

public class DeliveryQueen {
    private FoodDeliverable orderedFood;

    void chooseFood(FoodDeliverable food) {
        this.orderedFood = food;
    }

    void orderSomeFood() {
        this.orderedFood.deliverSomeFood();
    }
}

public class Main {

    public static void main(String[] args) {
        System.out.println("Hello and welcome ");

        DeliveryQueen dq = new DeliveryQueen();

        dq.chooseFood(new BurgerCastle());
        dq.orderSomeFood();
    }
}
interface FoodDeliverable {
    fun deliverSomeFood()
}

class PizzaCastle: FoodDeliverable {
    override fun deliverSomeFood() {
        print("deliver the tastiest pizza in the world")
    }
}

class BurgerCastle: FoodDeliverable {
    override fun deliverSomeFood() {
        print("deliver the tastiest burger in the world")
    }
}

class DeliveryQueen {
    private var orderedFood: FoodDeliverable = PizzaCastle()

    fun chooseFood(food: FoodDeliverable) {
        orderedFood = food
    }

    fun orderSomeFood() {
        orderedFood.deliverSomeFood()
    }
}

fun main() {
    println("Hello")

    val dq = DeliveryQueen()
    dq.chooseFood(BurgerCastle())
    dq.orderSomeFood()
}
interface FoodDeliverable {
    fun deliverSomeFood()
}

class PizzaCastle: FoodDeliverable {
    override fun deliverSomeFood() {
        print("deliver the tastiest pizza in the world")
    }
}

class BurgerCastle: FoodDeliverable {
    override fun deliverSomeFood() {
        print("deliver the tastiest burger in the world")
    }
}

class DeliveryQueen(var orderedFood: FoodDeliverable): FoodDeliverable by orderedFood {
    //private var orderedFood: FoodDeliverable = PizzaCastle()

    fun chooseFood(food: FoodDeliverable) {
        orderedFood = food
    }

    fun orderSomeFood() {
        orderedFood.deliverSomeFood()
    }
}

fun main() {
    println("Hello")

    val dq = DeliveryQueen(PizzaCastle())
    dq.chooseFood(BurgerCastle())
    dq.orderSomeFood()
}
Kotlin示例#1未明确使用by关键字:

public interface FoodDeliverable {
    void deliverSomeFood();
}

public class PizzaCastle implements FoodDeliverable {
    @Override
    public void deliverSomeFood() {
        System.out.println("deliver the tastiest pizza in the world");
    }
}

public class BurgerCastle implements FoodDeliverable {
    @Override
    public void deliverSomeFood() {
        System.out.println("deliver the tastiest burger in the world");
    }
}

public class DeliveryQueen {
    private FoodDeliverable orderedFood;

    void chooseFood(FoodDeliverable food) {
        this.orderedFood = food;
    }

    void orderSomeFood() {
        this.orderedFood.deliverSomeFood();
    }
}

public class Main {

    public static void main(String[] args) {
        System.out.println("Hello and welcome ");

        DeliveryQueen dq = new DeliveryQueen();

        dq.chooseFood(new BurgerCastle());
        dq.orderSomeFood();
    }
}
interface FoodDeliverable {
    fun deliverSomeFood()
}

class PizzaCastle: FoodDeliverable {
    override fun deliverSomeFood() {
        print("deliver the tastiest pizza in the world")
    }
}

class BurgerCastle: FoodDeliverable {
    override fun deliverSomeFood() {
        print("deliver the tastiest burger in the world")
    }
}

class DeliveryQueen {
    private var orderedFood: FoodDeliverable = PizzaCastle()

    fun chooseFood(food: FoodDeliverable) {
        orderedFood = food
    }

    fun orderSomeFood() {
        orderedFood.deliverSomeFood()
    }
}

fun main() {
    println("Hello")

    val dq = DeliveryQueen()
    dq.chooseFood(BurgerCastle())
    dq.orderSomeFood()
}
interface FoodDeliverable {
    fun deliverSomeFood()
}

class PizzaCastle: FoodDeliverable {
    override fun deliverSomeFood() {
        print("deliver the tastiest pizza in the world")
    }
}

class BurgerCastle: FoodDeliverable {
    override fun deliverSomeFood() {
        print("deliver the tastiest burger in the world")
    }
}

class DeliveryQueen(var orderedFood: FoodDeliverable): FoodDeliverable by orderedFood {
    //private var orderedFood: FoodDeliverable = PizzaCastle()

    fun chooseFood(food: FoodDeliverable) {
        orderedFood = food
    }

    fun orderSomeFood() {
        orderedFood.deliverSomeFood()
    }
}

fun main() {
    println("Hello")

    val dq = DeliveryQueen(PizzaCastle())
    dq.chooseFood(BurgerCastle())
    dq.orderSomeFood()
}
Kotlin示例#2明确使用by关键字:

public interface FoodDeliverable {
    void deliverSomeFood();
}

public class PizzaCastle implements FoodDeliverable {
    @Override
    public void deliverSomeFood() {
        System.out.println("deliver the tastiest pizza in the world");
    }
}

public class BurgerCastle implements FoodDeliverable {
    @Override
    public void deliverSomeFood() {
        System.out.println("deliver the tastiest burger in the world");
    }
}

public class DeliveryQueen {
    private FoodDeliverable orderedFood;

    void chooseFood(FoodDeliverable food) {
        this.orderedFood = food;
    }

    void orderSomeFood() {
        this.orderedFood.deliverSomeFood();
    }
}

public class Main {

    public static void main(String[] args) {
        System.out.println("Hello and welcome ");

        DeliveryQueen dq = new DeliveryQueen();

        dq.chooseFood(new BurgerCastle());
        dq.orderSomeFood();
    }
}
interface FoodDeliverable {
    fun deliverSomeFood()
}

class PizzaCastle: FoodDeliverable {
    override fun deliverSomeFood() {
        print("deliver the tastiest pizza in the world")
    }
}

class BurgerCastle: FoodDeliverable {
    override fun deliverSomeFood() {
        print("deliver the tastiest burger in the world")
    }
}

class DeliveryQueen {
    private var orderedFood: FoodDeliverable = PizzaCastle()

    fun chooseFood(food: FoodDeliverable) {
        orderedFood = food
    }

    fun orderSomeFood() {
        orderedFood.deliverSomeFood()
    }
}

fun main() {
    println("Hello")

    val dq = DeliveryQueen()
    dq.chooseFood(BurgerCastle())
    dq.orderSomeFood()
}
interface FoodDeliverable {
    fun deliverSomeFood()
}

class PizzaCastle: FoodDeliverable {
    override fun deliverSomeFood() {
        print("deliver the tastiest pizza in the world")
    }
}

class BurgerCastle: FoodDeliverable {
    override fun deliverSomeFood() {
        print("deliver the tastiest burger in the world")
    }
}

class DeliveryQueen(var orderedFood: FoodDeliverable): FoodDeliverable by orderedFood {
    //private var orderedFood: FoodDeliverable = PizzaCastle()

    fun chooseFood(food: FoodDeliverable) {
        orderedFood = food
    }

    fun orderSomeFood() {
        orderedFood.deliverSomeFood()
    }
}

fun main() {
    println("Hello")

    val dq = DeliveryQueen(PizzaCastle())
    dq.chooseFood(BurgerCastle())
    dq.orderSomeFood()
}
我认为我的两个kotlin示例都很好。我看不出有什么不同。那么,如果没有好处,我为什么要添加FoodDelivery by orderedFood呢?谢谢:)

Kotlin示例#1
DeliveryQueen
不是一个
FoodDelivery
,因为它没有实现接口,所以它不是一个正确的组合实现。要修复Kotlin示例#1中的FoodDeliverable,您必须实现
FoodDeliverable
,这将迫使您覆盖其方法:

class DeliveryQueen: FoodDeliverable  {
    private var orderedFood: FoodDeliverable = PizzaCastle()

    override fun deliverSomeFood() {
        orderedFood.deliverSomeFood()
    }

    fun chooseFood(food: FoodDeliverable) {
        orderedFood = food
    }

    fun orderSomeFood() {
        orderedFood.deliverSomeFood()
    }

}
了解如何实现
deliverysomefood()
,即使它只是将调用传递给代理
orderedFood
?这就是kotlin在
by
中的委托,如kotlin示例#2中所述,默认情况下,您获得了实现,并且您只在需要添加额外逻辑的地方覆盖
方法。
当你的界面有更多的方法时,好处会更加明显,在这种情况下,
by
的委托可以为你节省大量的样板文件

Kotlin示例#1中
DeliveryQueen
不是一个
FoodDelivery
,因为它没有实现接口,所以它不是一个正确的组合实现。要修复Kotlin示例#1
中的FoodDeliverable
,您必须实现
FoodDeliverable
,这将迫使您覆盖其方法:

class DeliveryQueen: FoodDeliverable  {
    private var orderedFood: FoodDeliverable = PizzaCastle()

    override fun deliverSomeFood() {
        orderedFood.deliverSomeFood()
    }

    fun chooseFood(food: FoodDeliverable) {
        orderedFood = food
    }

    fun orderSomeFood() {
        orderedFood.deliverSomeFood()
    }

}
了解如何实现
deliverysomefood()
,即使它只是将调用传递给代理
orderedFood
?这就是kotlin在
by
中的委托,如kotlin示例#2中所述,默认情况下,您获得了实现,并且您只在需要添加额外逻辑的地方覆盖
方法。

当你的界面有更多的方法时,好处会更加明显,在这种情况下,
by
的委托可以为你节省大量的样板文件

您的示例没有以正常的方式使用委派,这就是您没有看到好处的原因

DeliveryQueen
将其方法调用转发给实现
FoodDelivable
的某个实例,这是正常模式;但您的案例有两个重要区别:

  • 它可以在创建后更改该实现,并且
  • 转发方法(
    orderSomeFood()
    )与它转发到的方法(
    deliverSomeFood()
    )不同
如果没有这些,您可以通过以下方式实现该类:

class DeliveryQueen(orderedFood: FoodDeliverable): FoodDeliverable by orderedFood
…并且没有正文(需要添加或重写的任何方法除外)

(有关Kotlin不支持在运行时更改委托的原因,请参见。)

很明显,像这样的一个玩具例子并不能很好地展示委托的好处,但是想象一下如果
FoodDeliverable
有更多的方法;如果没有Kotlin对委派的支持,
DeliveryQueen
将需要大量样板文件,如:

    fun deliverSomeFood() {
        orderedFood.deliverSomeFood()
    }

    fun payDriver(price: BigDecimal, tip: BigDecimal) {
        orderedFood.payDriver(price, tip)
    }

    fun leaveReview(comment: String, stars: NumberOfStars, promptness: EarlyOrLate, foodQuality: QualityMetric): Review {
        return orderedFood.leaveReview(comment, stars, promptness, foodQuality)
    }

    fun <T : ConnectionMethod> contactRestaurant(method: T): Connection<T> {
        return orderedFood.contactRestaurant(method)
    }

    // …and so on…
fun deliverSomeFood(){
订购食品。送货上门食品()
}
有趣的付费驱动程序(价格:BigDecimal,小费:BigDecimal){
订购食品。付费司机(价格、小费)
}
有趣的假期回顾(评论:字符串,星星:NumberOfStars,敏捷性:EarlyOrLate,食物质量:QualityMetric):回顾{
退货定购食品。离开评论(评论、星级、及时性、食品质量)
}
娱乐联系餐厅(方法:T):连接{
退货订购食品。联系餐厅(方法)
}
//……等等…
…所有这些都需要保持最新


(方法的数量可能会变得相当多。例如,我记得必须用Java为
Java.sql.Connection
编写一个包装器,其中超过50个方法…委派将节省大量的样板文件!)

您的示例使用委派的方式与通常预期的方式不同,这就是为什么你没有看到好处

DeliveryQueen
将其方法调用转发给实现
FoodDelivable
的某个实例,这是正常模式;但您的案例有两个重要区别:

  • 它可以在创建后更改该实现,并且
  • 转发方法(
    orderSomeFood()
    )与它转发到的方法(
    deliverSomeFood()
    )不同
如果没有这些,您可以通过以下方式实现该类:

class DeliveryQueen(orderedFood: FoodDeliverable): FoodDeliverable by orderedFood
…并且没有正文(需要添加或重写的任何方法除外)

(有关Kotlin不支持在运行时更改委托的原因,请参见。)

很明显,像这样的一个玩具例子并不能很好地展示委托的好处,但是想象一下如果
FoodDeliverable
有更多的方法;如果没有Kotlin对委派的支持,
DeliveryQueen
将需要大量样板文件,如:

    fun deliverSomeFood() {
        orderedFood.deliverSomeFood()
    }

    fun payDriver(price: BigDecimal, tip: BigDecimal) {
        orderedFood.payDriver(price, tip)
    }

    fun leaveReview(comment: String, stars: NumberOfStars, promptness: EarlyOrLate, foodQuality: QualityMetric): Review {
        return orderedFood.leaveReview(comment, stars, promptness, foodQuality)
    }

    fun <T : ConnectionMethod> contactRestaurant(method: T): Connection<T> {
        return orderedFood.contactRestaurant(method)
    }

    // …and so on…
fun deliverSomeFood(){
订购食品。送货上门食品()
}
有趣的付费驱动程序(价格:BigDecimal,小费:BigDecimal){
订购食品。付费司机(价格、小费)
}
有趣的假期回顾(评论:字符串,星星:NumberOfStars,敏捷性:EarlyOrLate,食物质量:QualityMetric):回顾{
退货定购食品。离开评论(评论、星级、及时性、食品质量)
}
娱乐联系餐厅(方法:T):连接{
退货订购食品。联系餐厅(方法)
}
//……等等…
……好的