我在继承中修复“ getters”和“ setters”时遇到问题

时间:2018-11-20 19:23:33

标签: java

请忍受,这是我第一次使用Java处理继承。 :)

我有以下超类,用于标识船只并返回船只的名称及其长度:

public class Ship {

    private String name="";
    private int length=0;

    public Ship(String name, int length) {
        this.setName(name);
        this.length = length;
    }

    public static String getName() {
        return name;
    }

    public void setName(String name) {
        Ship.name = name;
    }

    public String toString() {
        return " Ship "+name+" l="+ length ;
    }

}

这是通过创建一个对象来完成的,例如:

Ship SSAnne = new Ship("S.S. Anne", 45);

然后,我有了从我的超类扩展来的“子类”,这些子类定义了集装箱船,油轮和游轮的对象。这是我的集装箱船子类(其他类型的船是相同的,除了不同的变量名):

public class ContainerShip extends Ship {

    private int teu=0;

    public ContainerShip(String string, int length, int teu) {
        super(getName(), length);
        this.teu = teu;
    }

    public void setName(String name) {
        ContainerShip.name = name;
    }

    public String toString() {
        return super.toString()+" container carrier with "+teu+" TEU";
    }

}

这些子类的调用方式如下:

ContainerShip dave = new ContainerShip("Dave Oest", 100, 2000);

其中添加了一个额外的变量,并且前两个参数是超类中的相同变量。

我的问题是我的“名称”变量的获取器和设置器。当我运行代码时,它会为所有对象(甚至是子类中的对象)生成“ S.S. Anne”名称。我似乎无法为子类“获得”船名。

有人可以帮助我如何在我的子类中正确设置吸气剂和吸气剂吗?


@GBlodgett:

public class Ship {

    private String name="";
    private int length=0;

    public Ship(String name, int length) {
        this.setName(name);
        this.length = length;
    }

    public void getName(String name) {
        this.name = name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String toString() {
        return " Ship "+name+" l="+ length ;
    }

}

public class ContainerShip extends Ship {

    private int teu=0;

    public ContainerShip(String string, int length, int teu) {
        super(getName(), length);
        this.teu = teu;
    }

    public void getName(String name) {
        this.name = name;
    }

    public void setName(String name) {
            this.name = name;
    }

    public String toString() {
        return super.toString()+" container carrier with "+teu+" TEU";
    }

}

4 个答案:

答案 0 :(得分:3)

您已将name声明为static,这意味着该类的所有实例之间仅共享一个副本。您要删除static关键字,然后在getter和setter中使用this关键字,该关键字指向在其上调用方法的对象:

 public void setName(String name) {
    this.name = name;
}

在这种情况下,setName方法在两个类中都相同,并且您将不需要在子类中覆盖它


更新后的代码的第一个问题是,在显式调用构造函数时无法引用实例方法。不用调用getName(),而是将传递的String参数传递给构造函数:

public SubClass(String string, int length, int teu) {
    super(string, length);
    this.teu = teu;
}

然后在您的getName()方法中,将其视为设置器。您应该返回name字段:

public String getName() {
    return this.name;
}

这导致了您的最后一个问题:您正在使用name的超类副本。由于您将其标记为私有,因此其他班级将无法访问它。您可以给ContainerShip自己的name变量,也可以对name中的Ship进行保护,或者再次使用super,例如:

public void setName(String name) {
    super.setName(name);
} 

答案 1 :(得分:1)

您无法从静态方法访问实例变量,

private String name="";
private int length=0;

这些是实例变量,您的方法在其中声明为static

public static String getName() {

在实现继承时,您应该始终记住的一件事。

请勿在变量声明中使用静态字或在方法声明中使用静态字。

仅当我们使用实例变量和实例(非静态)方法处理所有事务时,才会发生继承。因此,您将不得不改变几件事,

更改此内容

public static String getName() {

public String getName() {

类似地,您不能使用类名称访问实例变量,并且对于引用当前对象,可以使用this。因此改变

public void setName(String name) {
    Ship.name = name;
}

public void setName(String name) {
    this.name = name;
}

此外,在此构造函数中,您遇到了问题,

public ContainerShip(String string, int length, int teu) {
    super(getName(), length);
    this.teu = teu;
}

您没有使用string变量作为第一个参数。您需要从中更改此超类,

super(getName(), length);

super(string, length);

这样,无论传递给构造函数的什么,都将传递给超类的构造函数。

您应该首先解决这些问题。

此外,一旦您使用ContainerShip类创建对象,它就可以访问父类Ship的getter / setter方法,因为您的子类将继承那些称为继承的方法。它是一个广泛的主题,随着您的进行,您将了解更多此类构造。让我知道您是否对继承有任何疑问。

在超类中将实例变量声明为private时,实例变量对子类不直接可见,只能通过公共getter / setter进行访问,但是如果要直接访问它们,您可以将它们声明为受保护的,并且可以直接访问它们。继承是您可以从子类中的超类访问变量的原因,前提是它们未声明为私有。 Private表示只能在其自己的类中访问。

答案 2 :(得分:0)

您可以使用接口定义Type和Abstract类来定义默认行为。例如:

interface Ship {
    String getName();
    void setName();
}

abstract class DefaultShip implements Ship {
    private int length;

    public DefaultShip(int length) {
        this.length = length;
    }

    public String toString() {
        return " Ship " + getName() + " l=" + this.length;
    }
}

public class ContainerShip extends DefaultShip {

    private int teu;
    private String name;

    public ContainerShip(String name, int length, int teu) {
        super(length);
        this.name = name;
        this.teu = teu;
    }

    public void getName(String name) {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String toString() {
        return super.toString() +" container carrier with " + this.teu + " TEU";
    }
}

答案 3 :(得分:0)

您不需要在子类中使用setter和getter来获取名称和长度值。 仅当您要覆盖它们时。

船超类

public class Ship {

    private String name;
    private int length;

    public Ship(String name, int length) {
        this.name = name;
        this.length = length;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String toString() {
        return " Ship "+name+" l="+ length ;
    }

}

ContainerShip子类

public class ContainerShip extends Ship {

    private int teu;

    public ContainerShip(String string, int length, int teu) {
        super(string, length);
        this.teu = teu;
    }

    public String toString() {
        return super.toString()+" container carrier with "+teu+" TEU";
    }

}

主要方法

public static void main(String[] args) {

        ContainerShip cont = new ContainerShip("Name", 100, 4);
        System.out.println(cont.getName());
        cont.setName("new name");
        System.out.println(cont.getName());
}

输出:

  

名称

     

新名称