Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/343.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 对派生类中的成员变量使用派生类型_Java_Oop_Gwt_Object Oriented Analysis - Fatal编程技术网

Java 对派生类中的成员变量使用派生类型

Java 对派生类中的成员变量使用派生类型,java,oop,gwt,object-oriented-analysis,Java,Oop,Gwt,Object Oriented Analysis,我现在有一个类a,它有一些我想在B中使用的功能。a有一个Button类型的成员变量,而在B中我想使用IconButton类型(从Button派生) 课程如下: public class A { protected Button x = new Button(); A() { x.xx(); } public void doFirstThing() { x.xx(); } Button getButton()

我现在有一个类a,它有一些我想在B中使用的功能。a有一个Button类型的成员变量,而在B中我想使用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
}
A类扩展A0{
//大部分为空,代码取自A0
}
B类扩展A0{
//在这里定制东西
}
或者有没有其他更好的方法来解决这个问题

这是我的GWT应用程序中的一个组件。所以,如果我像@king_-nak所说的那样声明,那么我的组件中将有两个按钮。或者,如果我还可以接受另一种解决方法,我可以删除B中的原始按钮,例如
x.removeFromParent()
或类似的东西,但这样做只会成为一个全新的坏习惯。

一个简单的(多态的)方法是重写类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;
    }
}

你的变通办法是个坏主意。你失去了很多打字安全。例如,您可以将
B
的结构更改为
x=new Button()并忘记演员阵容。您的程序仍将编译,但在运行时失败

我认为您使用通用超类是正确的。您可以使用成员
tx
A0
定义为
A0
。也许有更好的解决方案,但如果没有大局,很难判断

  • 提取按钮界面 public interface Button { void init(); } 公共界面按钮{ void init(); }
  • 创建PlainButton(您的ex Button)类: 公共类PlainButton实现了这个按钮{ 公共void init(){ xx(); } 私有无效xx(){ } }
  • 创建图标按钮类: 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() { } } 公共类IconButton实现按钮{ 公共void init(){ yy(); zz(); } 私人无效yy(){ } 私人空间zz(){ } }
  • 创建ButtonRapper类(您的ex A和/或B类): 公共类按钮敲击器{ 专用最终T按钮; 公用按钮振打器(T按钮){ this.button=按钮; this.button.init(); } 公共getButton(){ 返回按钮; } }
  • 使用:

    ButtonWrapper A = new ButtonWrapper(new PlainButton()); ButtonWrapper B = new ButtonWrapper(new IconButton()); ButtonRapper A=新按钮Rapper(新的PlainButton()); ButtonRapper B=新按钮Rapper(新图标按钮());

  • 如果您唯一关心的是
    B
    应该有一个
    IconButton
    而不是它的基本
    按钮,为什么不在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拥有它的图标按钮,并有2个对它的引用(
    B.ib
    和继承的
    A.B

    ,以防您不想使用泛型: 这种方法与此相反,但我发现只要您不使用按钮在
    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;
            }
        }
    

    关于
    抽象类A
    字段Tx
    ,以及
    类B扩展了类A
    ,我不确定您是否打算在某个时刻构造类A
    的实例。如果是这样的话,那么就可以了,除了不需要
    IconButton getButton()
    。如果不创建
    A
    的实例,则将其抽象为是IconButton是B的一个实现细节。为什么要向这些类的客户端公开IconButton和Button?在这种情况下,如果你问我的话,有一些工厂设计模式会导致更干净的代码。如果
    getButton
    方法返回的实例类型取决于重写它的类,那么我宁愿采用这种方式,而不是实现工厂方法。如果类型(这取决于类),为什么要这样做是否从
    按钮继承?一个干净的方法是一个接口,但我不确定在这种情况下,因为我看不清楚OP的缩进。呵呵,在设计软件解决方案时,这种讨论是很常见的。@DarshanMehta:我想你没有抓住我问题的重点。事实上,我并不关注getButton()。这只是我试图在B中使用x进行欺骗的一个例子。根本问题是x可以在A和B中的许多地方调用,因此我不认为我们可以像这样将事情“分组”到getButton方法:(啊……我忘了提到这是我的GWT应用程序中的一种组件。因此,如果我像你说的那样声明,那么我的组件中将有两个按钮……(或者如果我可以接受另一种解决方法,我可以删除B中的原始按钮。但这只是一种全新的坏做法)实例化B时只有一个按钮。当子类提供按钮时,A从不创建按钮。或者你正在处理生成的代码,不能使用这种方法?哇……看起来这就是我需要的。
    
    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;
            }
        }