请忍受,这是我第一次使用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";
}
}
答案 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());
}
输出:
名称
新名称