kal*_*dev 18 java inheritance variadic-functions
我还没有找到解决这个问题的优雅方法.我有一个抽象类,其他几个类继承了一个抽象方法,可以包含0到4-5个不同类型的参数.
public abstract class Item {
public abstract void use();
}
Run Code Online (Sandbox Code Playgroud)
例如,我有一个继承了这个并且在重写use()时没有参数的Book类,我有一个Key类,它继承并在重写时将String和Queue作为参数...
我已经尝试过使用泛型,但是当它实际上取决于类时,我必须输入使用的数字,例如Item.
public abstract class Item<T,U> {
public abstract void use(T arg1, U arg2); //Number of arguments/types could be more or less
}
Run Code Online (Sandbox Code Playgroud)
我已经尝试发送一个对象的变量列表,但对象类型总是可变的,我不确定在继承类中接收的语法.
public abstract class Item<T> {
public abstract void use(T... arguments);
}
public class Book extends Item<?> {
public void use(?);
}
public class Book extends Item<String, Queue> { //Wrong number of arguments since I can't use Item<T...>
public void use(String str, Queue q); //fails
}
Run Code Online (Sandbox Code Playgroud)
我可能只是做错了什么 - 有人可以提供任何帮助或见解吗?
小智 15
我一直在努力解决同样的问题,并没有一个完美的答案,但我可以给你一些考虑的事情.首先,您基本上是在尝试做一些本质上违反面向对象编程的事情,即您正在尝试创建一个可变接口.接口的关键是获取对象的抽象版本(例如Item而不是Book)的代码知道如何调用use()方法.这意味着他们必须知道可以传递给use()方法的内容.如果答案取决于抽象类或接口的实现,那么你需要确保使用它的代码实际上知道它正在使用什么样的实现(Book等),否则它不会知道如何调用use ()具有适当的参数.听起来你需要严格地重构你的代码.
但是,有一种方法可以回答您提出的问题,而无需重构架构.您可以创建一个类,其中的数据是可能传递给use()方法的所有不同类型的参数,让调用代码设置该类的字段,然后将其传递给use()方法.例如:
public class UseParameters {
private String string;
private Queue queue;
// Any other potential parameters to use(...)
public void setString(String string) {
this.string = string;
}
public String getString() {
return string;
}
// All of the other accessor methods, etc.
}
Run Code Online (Sandbox Code Playgroud)
然后,您可以在Item中定义use方法,如下所示:
public abstract void use(UseParameters params);
Run Code Online (Sandbox Code Playgroud)
使用Item的任何代码都必须适当地设置对象的参数:
Item item = // However you're going to get the item
UseParameters params = new UseParameters();
params.setString("good string");
params.setQueue(new Queue());
item.use(params);
Run Code Online (Sandbox Code Playgroud)
我只是想指出,如果上面的代码知道Item是一本书(它是如何知道设置字符串和队列,那么为什么不只是得到一本书并跳过需要一个带有变量use()方法的抽象类完全?但我离题了.无论如何,本书将实现use()方法,如下所示:
@Override
public void use(UseParameters params) {
if(params.getString == null || params.getQueue() == null)
// throw exception
// Do what books do with strings and queues
}
Run Code Online (Sandbox Code Playgroud)
我认为这可以让你得到你想要的,但我认为你应该考虑重构.
你想要的是价值对象模式.
定义一个类,将各种参数类型封装到一个值对象中,并使抽象方法接受此类型的参数.您正在考虑的每个参数变体都有自己的值类.
然后只需向类中添加泛型类型,并使抽象方法接受该类型的参数:
public abstract class Item<V> {
public abstract void use(V v);
}
Run Code Online (Sandbox Code Playgroud)
要使用它,假设MyItem
需要一个类型的值对象MyValueClass
:
public class MyItem extends Item<MyValueClass> {
public void use(MyValueClass v) {
}
}
Run Code Online (Sandbox Code Playgroud)
如果要用作参数的类型总是可变的,我没有看到使用泛型的理由.只需使用普通对象类型:
public abstract class Item {
public abstract void use(Object ... arguments);
}
public class Book extends Item {
public void use(Object ... arguments) { ... }
}
Run Code Online (Sandbox Code Playgroud)