我确信这有一些解决方案或模式,但我无法明确表达问题以找到正确的答案。
我有一个界面,ICar:
public interface ICar {
void SetMake(String make);
String GetMake();
}
我有一节课,Car:
public class Car implements ICar {
private String make;
public void SetMake(String make) { this.make = make; }
public String GetMake() { return make; }
我在另一个课程中有一个方法,它不知道Car。本着多态性的精神,我想让这个方法返回一个ICar,这样有人就可以创建自己的ICar实现并将这个方法用于他们的汽车:
...//class preamble
public ICar myMethod() {
ICar myCar = new ICar();
myCar.SetMake("Ferrari");
return myCar;
}
我不确定为什么这样的事情无法奏效。由于ICar包含SetMake方法,因此每个实现都必须包含此方法。当然,jvm可以以某种方式排队方法调用,然后在方法的具体结果可用时运行它们吗?
另一个想法是将新创建的ICar实现作为参数传递给myMethod并调用其方法,但我觉得这可能不是一个干净的实现,因为我每次都需要创建一个Car实例。此外,如果没有无参数构造函数,我将不得不使用虚拟数据实例化它(也不干净)。
我觉得我对如何实现这样的事情缺乏一些了解,并且想知道是否有人可以提供帮助?
感谢。
答案 0 :(得分:1)
这样做的一种方法是将类类型作为参数提供,并使其通用:
public <T extends ICar> T myMethod(Class<T> type) {
try {
T myCar = type.newInstance(); // T needs a visible no-args constructor
myCar.SetMake("Ferrari");
return myCar;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
(另请注意,我通过在RuntimeException
中包装任何内容来处理异常)
然后你需要这样称呼它:
Car car = myMethod(Car.class);
更灵活的方法是引入工厂接口并将工厂实例传递给myMethod
,ICar
使用它来创建具体的public interface ICarFactory<T extends ICar> {
T createCar();
}
...
public <T extends ICar> T myMethod(ICarFactory<T> factory) {
T myCar = factory.createCar();
myCar.SetMake("Ferrari");
return myCar;
}
...
Car car = myMethod(carFactory);
。工厂仍然是通用的:
/>
答案 1 :(得分:0)
你需要这样做:
public ICar myMethod() {
ICar myCar = new Car();
myCar.SetMake("Ferrari");
return myCar;
}
而不是
public ICar myMethod() {
ICar myCar = new ICar();
myCar.SetMake("Ferrari");
myCar.return;
}
这句话:myCar.return;
在这里几乎没有意义......因为ICar是一个你不能做的界面ICar myCar = new ICar()
答案 2 :(得分:0)
您无法实例化接口,因此new ICar()
不是一个选项。例如,setMake应该设置一个实例变量,但是Interface没有实例变量。
但是,您可以执行以下操作:
return new ICar() {
String m;
@Override
public void setMake(String make)
{
m = make;
}
@Override
public String getMake()
{
return m;
}
};
通过这种方式,您将创建一个实现接口的对象。
虽然这个答案提供了一个回答问题的特定示例(就像简单地实例化Car对象一样),但是关于接口的更大问题是可以返回在接口中实现的任何Object。除了允许委托创建对象之外,还有许多设计模式。例如,人们可能会考虑Factory Pattern。
答案 3 :(得分:0)
您无法创建新界面,但可以返回一个。
public ICar myMethod() {
ICar myCar = new Car();
myCar.SetMake("Ferrari");
return myCar;
}
接口是指它基本上说的合同#34;这是一个ICar
它可以是Car
,RedCar
和一千种不同的实现,但你不会#39知道哪个&#34; 。
这就是多态的含义,无论谁使用myMethod
都不知道他得到了哪辆车,他只能知道contract
而不知道它们是如何实现的。
答案 4 :(得分:0)
我不确定我是否完全了解你的内容,但我认为你真正想做的是从抽象基类继承你的Car
,以便其他人可以实现其他类型的工具。
这样的事情:
public abstract class Vehicle {
public abstract void SetMake(String make);
public abstract String GetMake();
}
public class Car extends Vehicle {
private String make;
public void SetMake(String make) { this.make = make; }
public String GetMake() { return make; }
}
public class Truck extends Vehicle {
private String make;
public void SetMake(String make) { this.make = make; }
public String GetMake() { return make; }
}
public Vehicle myMethod() {
Vehicle myCar = new Truck();
myCar.SetMake("Ferrari");
return myCar;
}
答案 5 :(得分:0)
对于您已声明的方法myMethod()
“本着多态性的精神,我希望这种方法能够返回一个ICar,这样有人就可以创建自己的ICar实现并将这种方法用于他们的汽车:”
我从中理解的是,您希望myMethod()
使用不同具体类型的ICar
。
使用new operator
时会创建对象。您现有的代码无法编译,因为您无法实例化Interfaces的对象。为了解决编译错误,我不希望你创建具体的汽车对象:
ICar car = new Car(); // this will solve compile error but avoid doing this in your code
避免使用
new
运算符,让代码的用户使用new并注入具体实现(您可能甚至不知道具体实现,因为它们是依赖于用户的代码用户)。
更改方法如下
...//class preamble
public ICar myMethod(ICar myCar, String make) {
myCar.SetMake(make);
return myCar;
}
我建议你学习:DIP principle
和dependency injection
,code to interface
。