Java和Kotlin中委托的比较
我试图理解继承与委派之争,以及如何实现这两者。 我的问题是,为什么我要用by关键字实现Kotlin?我认为这太过分了 让我给你举个例子。我们有一个可以点菜的应用程序。该应用程序名为DeliveryQueen 以下是Java示例: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
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示例#1DeliveryQueen
不是一个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):连接{
退货订购食品。联系餐厅(方法)
}
//……等等…
……好的