【问题标题】:Inheriting java constructors继承java构造函数
【发布时间】:2013-09-14 17:20:04
【问题描述】:

我有一个超类“BuildingMaterial”和大量子类,即石头、木头、粘土等。 所有子类的行为都类似: 1 个 int 字段,以单位存储建筑材料的数量。它们可以无参数构造或使用 int 构造。我已经知道 BuildingMaterial 的所有子类都将具有这两个构造函数,如何避免将它们编码到每个单独的类中? 下面是我不想在每节课上都做的一个例子:

public final class Stone extends BuildingMaterial {

    private int amount;

    //constructors
    public Stone() {
      amount = 0;
    }

    public Stone(int i) {
      amount = i;
    }

    //methods
    public int getAmount() {
      return amount;
    }
}

【问题讨论】:

    标签: java inheritance constructor


    【解决方案1】:

    很遗憾,答案是你不能。这是 Java 语言的限制。每个类都需要自己的构造函数——不能简单地从父类继承它们。 Java 编译器将为您生成的唯一构造函数是默认构造函数(无参数),并且仅在您根本不指定任何构造函数时才会生成。

    您可以在这里做的最好的事情是重构您的代码,使amount 在超类中:

    public abstract class BuildingMaterial {
    
        private int amount;
    
        //constructors
        public BuildingMaterial() {
          this(0);
        }
    
        public BuildingMaterial(int i) {
          amount = i;
        }
    
        //methods
        public int getAmount() {
          return amount;
        }
    
    }
    

    然后利用super 调用将超类的构造函数委托给您的子类:

    public final class Stone extends BuildingMaterial {
    
        //constructors
        public Stone() {
          super();
        }
    
        public Stone(int i) {
          super(i);
        }
    
    }
    

    请注意,我将无参数构造函数的主体从 amount=0; 更改为 this(0);。我个人认为这是更好的风格,因为如果您决定将其他初始化代码添加到您的构造函数主体中,您只需将其添加到 1 参数构造函数中,而零参数构造函数会将所有工作委托给它。

    【讨论】:

      【解决方案2】:

      你必须使用inheritance

      public abstract class BuildingMaterial {
          private int amount;
      
          //constructors
          public BuildingMaterial() {
              amount = 0;
          }
      
          public BuildingMaterial(int i) {
              amount = i;
          }
      
          //methods
          public int getAmount() {
              return amount;
          }
      }
      
      
      public class Stone extends BuildingMaterial {
          public Stone() {
              super();
          }
      
          public Stone(int i) {
              super(i);
          }
      }
      

      这样BuildingMaterial 的所有子类都可以通过getter 和setter 访问amount

      您可能将amount 声明为protected,因此您不需要getter 或setter 来访问子类中的该字段。

      【讨论】:

      • 我很好奇在这个例子中,哪里有必要将 BuildingMaterial 抽象化?
      • @user2651804 - 这不是*必要的*——这只是一个好习惯。 “建筑材料”是一个抽象概念,因此您永远不会期望实际创建 BuildingMaterial 类本身的实例(您只创建具体子类的实例)。通过使类抽象,您可以传达这个想法,Java 将确保没有人调用new BuildingMaterial()。请注意,我在回答中做出了相同的选择(使 BuildingMaterial 抽象)。
      • @user2651804 BuildingMaterial 可以是 concrete 对象吗?你想创建那个类的实例吗?有这样一个对象有意义吗?还是只想拥有其子类的实例?
      • @user2651804,对于finalStone 也是如此,将其设为final 将阻止任何进一步的专业化,即SomClasse extends Stone。但是您可能希望将不同种类的石头表示为 Stone 的子类,而不仅仅是 BuildingMaterial
      • 好吧,我明白你的观点了。为了可读性,我将声明 BuildingMaterial abstract 和 Stone final。非常感谢大家的回答=]
      【解决方案3】:

      使用 super 关键字来减少代码,但 super 是构造函数中的第一行

      public class Stone extends BuildingMaterial {
          public Stone() {
              super();
          }
      
          public Stone(int i) {
              super(i);
          }
      } 
      

      【讨论】:

        【解决方案4】:

        如果所有类都具有属性amount,则该属性可以从父类继承。在父类BuildingMaterial 中定义amount,然后使用super 从子类构造函数中调用父构造函数来设置amount 值。

        【讨论】:

        • 是的,我将在父类中定义数量。但我需要同时制作:new Stone() 和 new Stone(50)。我真的不明白你是否向我解释了我该怎么做:S
        • 如果你想使用构造函数来初始化具有该值的对象,那么你需要在每个子类中都有这样的构造函数。但另一种方法是在超类中使用 setAmount 方法,并在创建对象后使用该方法设置金额。
        【解决方案5】:

        不清楚你想在你的问题中避免什么......假设你正在谈论避免在所有子类中编写多个构造函数。我相信这是不可能的。下面定义 BuildingMeterial 构造函数并从 baseClass 调用 super() 的帖子将是使用的最佳解决方案。

        【讨论】:

          猜你喜欢
          • 2013-03-21
          • 2011-09-09
          • 2010-12-11
          • 2020-08-07
          • 1970-01-01
          • 2018-10-30
          • 1970-01-01
          • 1970-01-01
          • 2023-04-04
          相关资源
          最近更新 更多