【问题标题】:Is this the only way to make inherited objects?这是制作继承对象的唯一方法吗?
【发布时间】:2018-11-23 08:05:30
【问题描述】:
public class Animal
{
    public String name;
    public boolean legs;
    public boolean eyes;

    public Animal(String name, boolean legs, boolean eyes)
    {
        this.name = name;
        this.legs = legs;
        this.eyes = eyes;
    }
}

public class Dog extends Animal
{
    String name;
    boolean legs;
    boolean eyes;
    public boolean vacinated;
    public boolean rabid;
    public Dog(boolean vacinated, boolean rabid, String name, boolean legs, boolean eyes)
    {
        super(name, legs, eyes);
        this.vacinated = vacinated;
        this.rabid = rabid;
    }
}

public class Bulldog extends Dog
{
    String name;
    boolean legs;
    boolean eyes;
    public boolean vacinated;
    public boolean rabid;
    public String breedtype;

    public Bulldog(String breedtype, String name, boolean legs, boolean eyes, boolean vacinated, boolean rabid)
    {
        super(vacinated, rabid, name, legs, eyes);
        this.breedtype = breedtype;
    }
}

如您所见,如果这种情况一直持续下去,换句话说,如果我有一个很长的继承线,我是否真的需要一遍又一遍地列出每个变量?我只是觉得有一种更有效的方法可以做到这一点。

【问题讨论】:

  • 我真的需要一遍又一遍地列出每个变量吗? - 不。您的变量是公开的,您可以从子类中访问它们。如果您决定遵循标准并将它们设为私有,您仍然可以通过 setter 和 getter 访问它们。所以,在这两种情况下,不,你不必重复它们。
  • 所以我不需要重新声明它们,但我需要在我的构造函数中将它们作为参数变量?
  • 没有。您当前在同一个类中有多个 name 变量。由于成员变量不是多态的,这几乎肯定不会达到您的预期。
  • @Andrew 是的,您仍然需要在构造函数中使用它们。但是您可以拨打super(...) 来避免重新分配它们。
  • 您需要对象和类的教程,而不是这个网站。

标签: java inheritance this parent super


【解决方案1】:

您的课程违反了 OOP。您应该定义可以由protected 继承给子类的公共属性。这意味着子类可以访问那些

其次,公共属性应该在父类中定义,不需要在子类中重新创建。

P/S:由 BlackFlash 评论更新。我将对此类常见属性使用私有修饰符。在这个问题的范围内,子类不需要访问父类的属性。

你的类应该改变如下:

public class Animal
{
  private String name;
  private boolean legs;
  private boolean eyes;

  public Animal(String name, boolean legs, boolean eyes)
  {
    this.name = name;
    this.legs = legs;
    this.eyes = eyes;
 }
}

public class Dog extends Animal
{
   private boolean vacinated;
   private boolean rabid;
   private Dog(boolean vacinated, boolean rabid, String name, boolean legs, boolean eyes)
    {
      super(name, legs, eyes);
      this.vacinated = vacinated;
      this.rabid = rabid;
  }
}

public class Bulldog extends Dog
{
   private String breedtype;
   public Bulldog(String breedtype, String name, boolean legs, boolean eyes, boolean vacinated, boolean rabid)
   {
    super(vacinated, rabid, name, legs, eyes);
    this.breedtype = breedtype;
  }
}

【讨论】:

  • 您应该定义可以被protected 继承给子类的公共属性 - 实际上,您应该将它们设为私有并改为定义setter 和getter。
  • @BackSlash:为什么不能将protected用于公共属性?
  • @htpvl 例如,因为protected 变量也可以被同一个包内的类看到。这意味着,如果在某些时候您需要操纵这些变量或更改某些行为,则必须进行重大更改,要求所有使用该变量的开发人员更新他们的代码。如果您将变量设为私有并编写 setter/getter,您将能够控制该变量并对这些方法进行任何更改,而不会破坏其他代码。 stackoverflow.com/a/8353371/1759845
  • @BackSlash:感谢您提供这些有用的信息。其实我不知道protected 可以在同一个包中访问。我通过 C++ 学习了 OOP,并且该语言中没有包。嗯,这是一个新的学习。再次感谢。
【解决方案2】:

这违反了整个 OOP 概念。您可以将父类中的公共变量作为protected 变量,以便该类及其子类可以访问它。

不仅可以在父类中定义和实现变量,还可以将常用方法定义为受保护的。

Read more here

【讨论】:

    【解决方案3】:

    以下是您正在做的问题之一的更简单示例:

    class A {
      String a;
    
      A(String a) { this.a = a; }
    }
    
    class B extends A {
      String a;
    
      A(String a) { super(a); }
    }
    

    这段代码可能会给出你意想不到的结果:

    B b = new B("hello");
    System.out.println(b.a);  // null
    

    这可能会让您感到惊讶,因为您似乎在 A 的构造函数中通过 super(a) 调用初始化了 a

    但更令人惊讶的是,如果将其转换为 A,它不会打印null

    System.out.println(((A) b).a);  // hello
    

    看起来很奇怪:当您将其视为不同的类型时,它会打印出不同的内容。

    这里的问题是Java中的字段不是多态的:B中的a隐藏A中的a。这两个字段都存在,但是当您在 B 类型的变量上引用 a 时,您会得到一个与在 A 类型的变量上引用 a 时不同的字段。

    为了“减少混乱”,不要在B 中重复a 的声明:

    class A {
      String a;
    
      A(String a) { this.a = a; }
    }
    
    class B extends A {
      A(String a) { super(a); }
    }
    

    现在:

    B b = new B("hello");
    System.out.println(b.a);  // hello
    System.out.println(((A) b).a);  // hello
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-07-16
      • 1970-01-01
      • 2017-11-10
      • 2014-09-07
      • 2017-06-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多