问题:我想要实现的是让Parent
类的实例将其局部变量的更改传播到直接从{{Child
派生的Parent
类实例1}}。我目前的方法是extend
Parent
类到Child
,但它没有提供任何方式来访问Parent
实例变量。
示例:让我们说父类存储一个包含名称的String
。我想要一个孩子来自父母,他的String
名字是"乔治"还有一个孩子来自父母,他的String
名字是"尼克"。当String
存储在" George"父母班级改变了"乔治"到了#Patrick; Patrick"我希望它能为他的孩子改变,但不是为了" Nick"。
这可以在没有太多计算开销的情况下完成吗?
代码参考:
public class Parent {
private String name;
public Parent(String name) {
this.name = name;
}
public void changeName(String newName) {
name = newName;
}
public String getName() {
return name;
}
}
public class Child extends Parent {
private String parentName;
/**
* Currently derives the String directly which won't react to
* changes to the Parent class.
*/
public Child(Parent p) {
this.parentName = p.getName();
}
public getParentName() {
return parentName;
}
}
public class mainApp {
public static void main(String[] cmdArgs) {
Parent George = new Parent("George");
Parent Nick = new Parent("Nick");
Child a = new Child(George);
Child b = new Child(Nick);
George.changeName("Patrick");
// Prints "George", should print "Patrick"
System.out.println(a.getParentName());
// Prints "Nick", should print "Nick"
System.out.println(b.getParentName());
}
}
解决方案:实际上可以使用Object Composition来实现上述目标。
通过保留对创建Parent
类实例时使用的原始Child
的引用,Parent
实例上执行的所有更改都将反映在Child
上实例。
通过这种方式,Child
也可以处于孤立状态,其中没有Parent
实例用于创建它。
解决方案代码:
public class Parent {
private String name;
public Parent(String name) {
this.name = name;
}
public void changeName(String newName) {
name = newName;
}
public String getName() {
return name;
}
}
// Extension is not required
public class Child {
private Parent parentReference;
public Child(Parent parentReference) {
this.parentReference = parentReference;
}
public getParentName() {
// We need to manually handle the case of a non-existent parent
if (parentReference == null) {
return "None";
} else {
return parentReference.getName();
}
}
}
public class mainApp {
public static void main(String[] cmdArgs) {
Parent George = new Parent("George");
Parent Nick = new Parent("Nick");
Child a = new Child(George);
Child b = new Child(Nick);
Child c = new Child(null);
George.changeName("Patrick");
// Prints "Patrick", should print "Patrick"
System.out.println(a.getParentName());
// Prints "Nick", should print "Nick"
System.out.println(b.getParentName());
// Prints "None", should print "None"
System.out.println(c.getParentName());
}
}
答案 0 :(得分:2)
您正在接受条款"家长"和"孩子"在你的例子中非常字面意义,但并不总是适用。
只有在类型和子类型之间存在固定关系时,才能使用继承。喜欢,"自行车是一种车辆"或者"长颈鹿是动物"。对于自行车和长颈鹿的每一个例子,这些关系是相同的。但你所描述的并不是这样的。
对于您的情况,您可以使用合成来建模。
Person
都有name
。Person
都有一个parent
(可能会留下null
表示“不知道”#34}或“#”关心")Person
都有零个或多个children
class Person {
String name;
Person parent;
Person(String name, Person parent) {
this.name = name;
this.parent = parent;
}
// etc (getters, setters)
}
public class MainApp {
public static void main(String[] cmdArgs) {
Person george = new Person("George", null);
Person nick = new Person("Nick", null);
Person a = new Person("a", george);
Person b = new Person("b", george);
Person c = new Person("c", nick);
// etc.
}
}
答案 1 :(得分:1)
将继承用于实际陈述的问题,它会非常复杂,当你开始扩展你的服务时你会遇到问题(组合将是一个更好的现实世界的方法,但是组合带来更大的学习曲线,但是给出了增加了更大灵活性的好处):
public abstract class ServiceProvider {
private String providerName;
private String clientName;
public ServiceProvider(String providerName, String clientName) {
this.providerName = providerName;
this.clientName = clientName;
}
public String getProviderName() {
return this.providerName;
}
public String getClientName() {
return this.clientName;
}
boolean validateContract();
}
public class MobileInternetProvider extends ServiceProvider {
public MobileInternetProvider(String providerName, String clientName) {
super(providerName, clientName);
}
public boolean validateContract() {
return ContractService.validateMobileInternetProvider(this.getClientName());
}
}
public abstract class MobileCellularProvider extends ServiceProvider {
public MobileCellularProvider(String providerName, String clientName) {
super(providerName, clientName);
}
public boolean validateContract() {
return ContractService.validateMobileCellularProvider(getContractNumber());
}
String getContractNumber();
}
public class MobileCellularProviderCardContract extends MobileCellularProvider {
public MobileCellularProviderCardContract(String providerName, String clientName) {
super(providerName, clientName);
}
public String getContractNumber() {
MobileContractService.getCardContractNumber(this.getClientName());
}
}
public class MobileCellularProviderMobileContract extends MobileCellularProvider {
public MobileCellularProviderMobileContract(String providerName, String clientName) {
super(providerName, clientName);
}
public String getContractNumber() {
MobileContractService.getMobileContractNumber(this.getClientName());
}
}
然后你会像这样使用它:
ArrayList<ServiceProvider> serviceProviders = new ArrayList<>();
serviceProviders.add(new MobileCellularProviderMobileContract(ProviderDef.PROVIDER_1, "Client 1"));
serviceProviders.add(new MobileCellularProviderMobileContract(ProviderDef.PROVIDER_1, "Client 2"));
serviceProviders.add(new MobileCellularProviderCardContract(ProviderDef.PROVIDER_1, "Client 3"));
serviceProviders.add(new MobileInternetProvider(ProviderDef.PROVIDER_1, "Client 4"));
serviceProviders.add(new MobileInternetProvider(ProviderDef.PROVIDER_2, "Client 1"));
原始回答
当实例化子类时,它具有超类'字段,因此更新子类'name
字段和更新超类'name
字段之间没有区别......只有一个字段在实例中。
所以当你说:
例如,假设父类存储包含名称的String。我希望3个孩子来自一个名字为“George”的父母,另外3个孩子来自一个名字为“Nick”的父母。当存储在“乔治”父类中的字符串从“乔治”变为“帕特里克”时,我希望为其子项更改它,而不是为“尼克”的子项更改。
这没有用。
你问题的标题是
是否有任何方法可以让父类的实例的变量直接被其子类(子类)引用?
答案是肯定的!但是您描述的问题与问题的标题无关