所以我认为我有一个非常基本的问题。假设您的项目com.bee.buzz中包含一个名为com.cow.moo的开源Java程序。
moo有很多很棒的课程,其中大部分是你不想碰的,但是有一些你做的。现在,在这一点上,最好的办法是扩展你想要修改的类,对吧? (我知道有很多关于扩展与实现的说法,但这些类都不是接口,所以这是不可能的。)我的问题是,说这是moo中的课程:
package com.cow.moo;
public class Milk {
private float currentMilk;
public int getMilk() { /* Stuff */ }
public float convertToGallons (float liquid) { /* More Stuff */ }
}
现在,我想在我的新课程中使用getMilk来扩展Milk。但是,Milk中的getMilk依赖于私有变量(如currentMilk)和其他我不会包含的函数(如convertToGallons。)如果我希望我的新函数正常工作,我是否必须包含其他变量和函数?我不想大量修改函数,只需添加一点就可以了。最好的方法是什么?
建立大型项目的一般提示也很有用。我认为这里的一些Java专家甚至不会花五秒钟来得出答案。谢谢你的时间。
答案 0 :(得分:6)
一般建议赞成合成优于继承。
说,你有一个接口和现有的实现,最适合你的需要,如
public interface MilkProvider { public float getMilk(); }
public class Milk implements MilkProvider { // same as you example }
并且需要另一个自定义实现,您可以像这样编写代码:
public class MyMilk implements MilkProvider {
private MilkProvider milk;
public MyMilk(int someValue) {
milk = new Milk(someValue); // unfortunatly we can't get rid of a depencency
// to the concrete class because we need to create
// something. An existing factory could help, but
// but usually there's none implemented.
}
public float getMilk() {
float result = milk.getMilk();
// do somethink with the result
return float;
}
}
答案 1 :(得分:1)
我认为在这种情况下,更好的解决方案将是多态(静态多态),或者您可以使用反射(不要使用这种方式)来访问私有变量。
答案 2 :(得分:1)
现在,我想在我的新课程中使用getMilk来扩展Milk。但是,Milk中的getMilk依赖于私有变量(如currentMilk)和其他我不会包含的函数(如convertToGallons。)如果我希望我的新函数能够正常工作,我是否必须包含其他变量和函数?
您不必包含 public 函数和变量。继承的核心概念是,作为子类,您可以免费获得子类中包含的所有父类的公共(和受保护)成员。所以你的子类(比如说HoneyMilk)可以从一开始就调用convertToGallons
。
在这种情况下覆盖getMilk
要复杂得多,因为它依赖于私有变量(您的子类无法访问)。我的建议是将你的思维方式从把班级视为“白盒子”转变为“黑匣子”。我的意思是你应该实现被覆盖的getMilk
版本,好像你实际上看不到Milk的源代码一样。虽然它可能看起来像一个迂回的解决方案(我的意思是,为什么我不能在这里调整这一行?!),这将迫使你只使用父类公开公开的子类来实现你的子类。它还强调抽象的重要性,这对于开发大型项目绝对至关重要。
答案 3 :(得分:0)
如果它们是公共的,你可以通过方法访问器(getters& setters)扩展类和访问实例变量。
您可以使用AOP (Aspect Oriented Programming)在运行时更改moo类,而无需更改其来源。
请仔细阅读一些Composition vs. Inheritance topics。
希望这会对你有所帮助。
答案 4 :(得分:0)
除非你使用丑陋的Java反射,否则你将无法使用私有类成员。如果我是你(并且更改不是太重,在这种情况下我会分叉原始项目),我会考虑在运行时修改代码或静态使用方面编织(面向方面编程)。 AspectJ可能看起来好像有一个很好的学习曲线,但它是一个很好的工具,可以在你的工具箱中完美匹配你的需求。