![](/img/trans.png)
[英]Java Inheritance: instance of object from parent class same for 2 child classes
[英]Java Inheritance: How to override instance variables/fields from parent class?
更新:我可以将变量从私有、static 或最终更改。
我有一个父母 class 和一个孩子 class。 我想在父class 中重用一个方法。 通常,这就像super.methodFromParentClass()
一样简单,你就完成了。 但是,当我这样做时,我想重用的方法是使用来自父 class 的实例变量数据,这是错误的,或者更确切地说,我不想要这种行为。 我在子class中有不同的初始化数据,需要传递到我想要重用的方法中。 如果您查看我想重用的方法(下面只是一个简单的示例,但想法是相同的),我将在其中创建多个对象,这些对象使用 class 的实例变量。所以你可以看到为什么当我调用super.methodIWantToReuse
时它不起作用,因为它会获取父数据并将其传递给对象,即使我真的希望它传递我在子 class 中初始化的数据。 我的真实示例还创建了更多的对象,并且我有更多的实例变量,所以如果可能的话,我真的想重用这段代码(DRY 原则)。
我怎样才能解决这个问题? 将使用getter即getFirstName()
并在子 class 中覆盖它们,因此当我调用super.methodIWantToReuse()
时使用运行时多态性,将获取/使用子 class 实例变量数据是唯一的方法???
public class ParentClass {
private static final String firstName = "Billy Ray";
private static final String lastName = "Cyrus";
private static final int age = 58;
private static final String city = "Hunstville";
public boolean methodIWantToReuse() {
Object1 obj1 = new Object(firstName, lastName);
Object2 obj2 = new Object(age,city);
Object3 obj3 = new Object(obj1, obj2);
Object4 obj4 = new Object(obj3);
// Passing in the objects created above as argument, which have the Parent instance variable data
return someRandomMethodHere(obj4);
}
public class ChildClass {
private static final String firstName = "Miley";
private static final String lastName = "Cyrus";
private static final int age = 27;
private static final String city = "Los Angeles";
public boolean methodIWantToReuse() {
// DOESN'T WORK CORRECTLY, because ends up using the instance variable data of PARENT class, but it
// needs to use CHILD class instance variable data
super.methodIWantToReuse();
}
您不能覆盖 class 的字段。 只有方法可以被覆盖。 在您的情况下,您必须使用 getter 并在子 class 中覆盖它们。
您的父 class 实例变量是私有的,因此您不能从子 class 更新它们。 因此,您可以使用参数化方法或为实例变量(或受保护的变量本身)创建受保护的 setter/getter。 在您的情况下,变量是最终的,因此您实际上甚至无法更新它们。 所以从技术上讲,不可能在父 class 中使用子 class 变量。
如果您将变量更新为protected
并删除static/final
修饰符(正如您在评论中提到的那样)。 从父 class 调用方法之前,在调用 super 方法之前更新变量数据。 你可以这样做:
方法 1:在调用父 class 方法之前更新父 class 中的数据。
父 Class:
public class ParentClass {
protected String firstName = "Billy Ray";
protected String lastName = "Cyrus";
protected int age = 58;
protected String city = "Hunstville";
public boolean methodIWantToReuse() {
// Passing in the objects created above as argument, which have the Parent
// instance variable data
Object1 obj1 = new Object(firstName, lastName);
Object2 obj2 = new Object(age,city);
Object3 obj3 = new Object(obj1, obj2);
Object4 obj4 = new Object(obj3);
return someRandomMethodHere(obj4);;
}
}
儿童 Class:
public class ChildClass extends ParentClass {
protected String firstName = "Miley";
protected String lastName = "Cyrus";
protected int age = 27;
protected String city = "Los Angeles";
public boolean methodIWantToReuse() {
// Update data in Parent class first
super.firstName = firstName;
super.lastName = lastName;
super.age = age;
super.city = city;
return super.methodIWantToReuse();
}
}
方法2:如果你想使用参数化方法使其无状态,你可以这样做:
父 Class:
public class ParentClass {
protected String firstName = "Billy Ray";
protected String lastName = "Cyrus";
protected int age = 58;
protected String city = "Hunstville";
public boolean methodIWantToReuse() {
return methodIWantToReuse(this.firstName, this.lastName, this.age, this.city);
}
public boolean methodIWantToReuse(String firstName, String lastName, int age, String city) {
// Passing in the objects created above as argument, which have the Parent
// instance variable data
Object1 obj1 = new Object(firstName, lastName);
Object2 obj2 = new Object(age,city);
Object3 obj3 = new Object(obj1, obj2);
Object4 obj4 = new Object(obj3);
return someRandomMethodHere(obj4);;
}
}
儿童 Class:
public class ChildClass extends ParentClass {
protected String firstName = "Miley";
protected String lastName = "Cyrus";
protected int age = 27;
protected String city = "Los Angeles";
public boolean methodIWantToReuse() {
// Update data in Parent class first
return super.methodIWantToReuse(this.firstName, this.lastName, this.age, this.city);
}
}
注意:保持局部变量名称与 class 级别变量相同不是一个好习惯。 但为了便于理解,将其保留在这里。
如果您真的是指instance variables
而不是您的static variables
(或class variables
),如示例中所示,您可以通过更改访问修饰符并删除final
关键字来使您的子类可以访问它们。
If, however, you actually mean static variables
, you cannot reassign them in each subclass as they would all share the same static variables defined by the ParentClass
, meaning the last loaded class would be the only result you get by calling your ParentClass#methodIWantToReuse
.
最好的办法是使用 OOP 通过使用所需的 arguments 实例化新的单个对象并使用它们来发挥您的优势。
我的意思是,而不是这样做:
public class Example {
public static class ParentClass {
protected String name;
protected int age;
public ParentClass() {
name = "The parent";
age = 35;
}
public String methodIWantToReuse() {
return name + " is " + age + " years old.";
}
}
public static class AChildClass extends ParentClass {
public AChildClass() {
name = "Alice";
age = 13;
}
}
public static class AnotherChildClass extends ParentClass {
public AnotherChildClass() {
name = "Bob";
age = 21;
}
}
public static void main(String[] args) {
// Prints "The parent is 35 years old."
System.out.println(new ParentClass().methodIWantToReuse());
// Prints "Alice is 13 years old."
System.out.println(new AChildClass().methodIWantToReuse());
// Prints "Bob is 21 years old."
System.out.println(new AnotherChildClass().methodIWantToReuse());
}
}
做这个:
public class Example {
public static class ParentClass {
protected String name;
protected int age;
// Variables instantiated here to not cause confusion
public ParentClass() {
name = "The parent";
age = 35;
}
public String methodIWantToReuse() {
return name + " is " + age + " years old.";
}
}
public static class ChildClass extends ParentClass {
public ChildClass(String name, int age) {
this.name = name;
this.age = age;
}
}
public static void main(String[] args) {
// Prints "The parent is 35 years old."
System.out.println(new ParentClass().methodIWantToReuse());
// Prints "Alice is 13 years old."
System.out.println(new ChildClass("Alice", 13).methodIWantToReuse());
// Prints "Bob is 21 years old."
System.out.println(new ChildClass("Bob", 21).methodIWantToReuse());
}
}
这也应该遵循 DRY 原则,因为您希望尽可能高效地重用您的代码,而不是在技术上一遍又一遍地编写相同的代码。
如您所见,我无需重写ParentClass#methodIWantToReuse
或调用ChildClass
的超级实现。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.