我目前有一个A类,它有一些我想在B中使用的功能.A有一个Button类型的成员变量,而在BI中想要使用IconButton类型(从Button派生)。
课程是这样的:
public class A {
protected Button x = new Button();
A() {
x.xx();
}
public void doFirstThing() {
x.xx();
}
Button getButton() {
return x;
}
}
public class B extends A {
B() {
x = new IconButton();
getButton().yy();
}
public void doSecondThing() {
getButton().zz();
}
IconButton getButton() {
return (IconButton) x;
}
}
public class Button {
public void xx() {
}
}
public class IconButton extends Button {
public void yy() {
}
public void zz() {
}
}
正如您所看到的,方法yy()
和zz()
仅在IconButton
中可用,因此我需要通过提供方法getButton
在B中执行“解决方法”
是的,通常我们在A中也有getButton()
方法,所以这对B来说并不是一个牵强附会的方法。
但我想知道,这是不是正确的做法,或者我做错了?
我还想过创建一个抽象类,例如A0,它将包含来自A的当前代码。然后我只做:
class A extends A0<Button> {
// mostly empty, code taken from A0
}
class B extends A0<IconButton> {
// custom things here
}
还有其他方法可以解决这个问题吗?
这是我的GWT应用中的一个组件。所以,如果我声明像@king_nak说的那样,那么我的组件中会有两个按钮。或者如果我可以使用另一种解决方法,我可以删除B中的原始按钮,例如x.removeFromParent()
或类似的东西,但它只会成为一个全新的糟糕做法。
答案 0 :(得分:1)
你的解决方法是一个坏主意。你失去了很多类型的安全。你可以,例如将B
的构造改为x = new Button();
并忘记演员。您的程序仍然可以编译但在运行时失败。
我认为你使用普通的通用超类是在正确的轨道上。您可以将A0
定义为A0<T extends Button>
,其成员为T x
。可能有一个更好的解决方案,但如果没有大局,很难说清楚。
答案 1 :(得分:0)
一种简单(多态)的方法是覆盖B类中的getButton
并返回IconButton
的实例,而不是在类中有引用,例如:
public class A {
public Button getButton(){
Button b = new Button();
b.xx();
return b;
}
}
public class B extends A {
@Override
public Button getButton(){
IconButton b = new IconButton();
b.yy();
b.zz();
return b;
}
}
答案 2 :(得分:0)
public interface Button { void init(); }
public class PlainButton implements Button { public void init() { xx(); } private void xx() { } }
public class IconButton implements Button { public void init() { yy(); zz(); } private void yy() { } private void zz() { } }
public class ButtonWrapper { private final T button; public ButtonWrapper(T button) { this.button = button; this.button.init(); } public T getButton() { return button; } }
使用:
ButtonWrapper A = new ButtonWrapper(new PlainButton()); ButtonWrapper B = new ButtonWrapper(new IconButton());
答案 3 :(得分:0)
如果你唯一担心的是B
应该有一个IconButton
而不是它Button
,为什么不在B中为它创建一个单独的成员,并让A用那个?
class A {
protected Button b;
public A() {
// By default, I use a Button
b = new Button();
}
// Subclasses can override which button I use
protected A(Button b) {
this.b = b;
}
}
class B extends A {
private IconButton ib;
public B() {
super(new IconButton());
ib = (IconButton) super.b;
}
// B can access it's IconButton through ib
// Users of A will see a Button
}
不需要抽象基类,泛型,包装器。让B拥有它的IconButton,并有2个引用它(B.ib
并继承A.b
)
答案 4 :(得分:0)
如果您不想使用泛型:
这种方法与best practices相反,但只要你不使用按钮在B
的构造函数中做任何事情,我就会发现它完全没问题:
public static class A {
protected Button x = null;
public A() {
x = createButton();
}
public Button getButton() {
return x;
}
protected Button createButton(){
Button result = new Button();
result.xx();
return result;
}
}
public static class B extends A{
public IconButton getButton() {
return (IconButton)x;
}
protected Button createButton(){
IconButton iconButton = new IconButton();
iconButton.yy();
iconButton.zz();
return iconButton;
}
}
现在,如果你想避免演员表演,你可以使用这种我很可能不会自己使用的疯狂方法。 警告使用风险由您自行承担:
public static class A {
protected Button x = null;
public A() {
x = createButton();
}
public Button getButton() {
return x;
}
protected Button createButton(){
Button result = new Button();
result.xx();
return result;
}
}
public static class B extends A{
//leave uninitialized so that when B gets constructed iconButton wont be reinitialized because it has been initialized by A's constructor call
private IconButton iconButton;
public IconButton getButton() {
return iconButton;
}
protected Button createButton(){
iconButton = new IconButton();
iconButton.yy();
iconButton.zz();
return iconButton;
}
}
<强>更新强>
如上所述,首选方法是避免继承,并在需要时使用组合。但是由于示例代码没有太多细节以便能够显示组合方法,我添加了另一种仍然使用继承的方法,避免了强制转换和构造初始化。 我认为最好在使用非并发框架(如Swing或GWT)而不是构造初始化时使用延迟初始化:
public static class A {
private Button x = null;
protected Button getButton() {
if (x == null) x = createButton();
return x;
}
private Button createButton(){
Button result = new Button();
result.xx();
return result;
}
}
public static class B extends A{
private IconButton iconButton;
public Button getButton() {
if (iconButton == null) iconButton = createButton();
return iconButton;
}
public IconButton getIconButton(){
getButton();
return iconButton;
}
private IconButton createButton(){
IconButton iconButton = new IconButton();
iconButton.yy();
iconButton.zz();
return iconButton;
}
}