【问题标题】:Implementing Interfaces and Inheritance实现接口和继承
【发布时间】:2014-03-05 04:34:35
【问题描述】:

我对接口和继承在实现阶段的工作方式有些困惑。这是一个快速的 ERD:

                                          <<interface>>
Animal                                    IColorChangable    
----------------------------              -----------------------
-color: int                               -----------------------
----------------------------              + changeColor()
----------------------------              -----------------------
         ^(Inheritance Triangle)             ^(Interface Triangle)
         |                                   |
         |                                   |
----------------------------------------------
Dog
----------------------------
-breed: string
----------------------------
+ getBreed()
----------------------------   

所以这里我有一只狗,它扩展了一个 Animal 类,并且还实现了一个 ColorChangable 接口。现在,colorchangeable 接口的工作是更新颜色,这是一个属于动物的属性,而不是狗。那么在狗类中更新颜色的正确方法是什么?实现变色的是狗,不是动物。现在我有这个:

public class Dog extends Animal implements IColorChangable
{
    private String breed;

    public Dog(int color, String breed)
    {
        super(color);
        this.breed = breed;
    }

    public void changeColor()
    {
        //How to have access to color?
    }
}

public interface IColorChangable
{
    public void changeColor();
}

【问题讨论】:

    标签: java oop inheritance interface


    【解决方案1】:

    因此,您只需将 setColor 和 getColor 添加到 Animal 类,但您应该将它们定义为公共方法。

    public void setColor(int color){
        this.color = color;
    }
    
    public int getColor(){
        return color;
    }
    

    然后在 changeColor 方法中,您可以通过 setColor 填充颜色。

    public void changeColor()
    {
        setColor(10); //for example
    }
    

    【讨论】:

    • 非常正确,但不是问题?
    • setColorgetColor 不必是 public,如果更适合这种情况,它们可以是 protected。另外值得注意的是,拥有一个吸气剂通常很有意义,但它并不是必需才能工作的。在更深层次上,如果Animal 具有color,那么可能值得考虑是否应该使用Animal 来实现IColorChangable
    【解决方案2】:

    你基本上有三个选择。您选择哪一种取决于您的要求、不变量的复杂性等。

    第一种选择是在Animal中将color声明为protected,然后可以直接在派生类中访问:

    public class Animal { 
        protected int color;
        ...
    }
    
    public class Dog extends Animal implements IColorChangable {
        ...
        @Override public void changeColor () {
            color = ...;
        }
    }
    

    第二种选择是在Animal中声明private,在这种情况下你不能直接用子类访问它,但是你可以给Animal添加一个setter(可选final,可选protected ,再次取决于您的规则)。例如,如果您想在基类中实现通用验证逻辑,这很有用:

    public class Animal { 
        private int color;
        ...
        protected final void setColor (int color) { // could be public, could be non-final
            this.color = color;
        }
    }
    
    public class Dog extends Animal implements IColorChangable {
        ...
        @Override public void changeColor () { 
            setColor(...);
        }
    }
    

    第三个选项是考虑这个问题:每一个动物的颜色可以改变吗? (在您的示例中,color 是一般Animal 的属性。)如果是这样,那么您可以让Animal 实现接口:

    public class Animal implements IColorChangable {
        private int color;
        ...
        @Override public void changeColor () {
            color = ...;
        }
    }
    
    public class Dog extends Animal {
        ...
    }
    

    这真的取决于你需要做什么。

    顺便说一句,在 Java 中通常不习惯像在 COM API 中那样以 I 开头的接口名称。此外,我们通常使用“属性”而不是“属性”。 :)

    【讨论】:

      【解决方案3】:
      color = 123;
      

      但您的属性颜色必须设置为公开或受保护。

      如果它是私有的,你需要在你的 Animal 类中做一个 setter:

      public void setColor(int color){
          this.color = color;
      }
      

      然后在你的方法中调用它:

      setColor(color);
      

      【讨论】:

        【解决方案4】:

        只需以普通会员身份访问即可:

        public void changeColor(int color)
        {
            this.color = color;
        }
        

        【讨论】:

        • 由于OP没有显示color的访问级别,我们不知道这是否可能(可能是private)。另外,为了清楚起见,建议使用@Override 标记(顺便提一下,如果缺少,Eclipse 默认会生成警告)。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-10-23
        • 1970-01-01
        • 2010-09-27
        • 2013-10-22
        • 2020-10-17
        • 2021-01-29
        • 1970-01-01
        相关资源
        最近更新 更多