带有变量参数列表的抽象方法

我还没有找到解决这个问题的优雅方法。 我有一个抽象类,其他几个类inheritance了一个抽象方法,可以包含0到4-5个不同类型的参数。

public abstract class Item { public abstract void use(); } 

例如,我有一个inheritance了这个并且在重写use()时没有参数的Book类,我有一个Key类,它inheritance并在重写时将String和Queue作为参数…

我已经尝试过使用generics,但是当它实际上取决于类时,我必须输入使用的数字,例如Item。

 public abstract class Item { public abstract void use(T arg1, U arg2); //Number of arguments/types could be more or less } 

我已经尝试发送一个对象的变量列表,但对象类型总是变量的,我不确定在inheritance类中接收的语法。

 public abstract class Item { public abstract void use(T... arguments); } public class Book extends Item { public void use(?); } public class Book extends Item { //Wrong number of arguments since I can't use Item public void use(String str, Queue q); //fails } 

我可能只是做错了什么 – 有人可以提供任何帮助或见解吗?

我一直在努力解决同样的问题,并没有一个完美的答案,但我可以给你一些考虑的事情。 首先,您基本上是在尝试做一些本质上违反面向对象编程的事情,即您正在尝试创建一个可变接口。 接口的关键是获取对象的抽象版本(例如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. } 

然后,您可以在Item中定义use方法,如下所示:

 public abstract void use(UseParameters params); 

使用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); 

我只想指出,如果上面的代码知道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 } 

我认为这可以让你得到你想要的东西,但我认为你应该考虑重构。

你想要的是价值对象模式 。

定义一个类,将各种参数类型封装到一个值对象中 ,并使抽象方法接受此类型的参数。 您正在考虑的每个参数变体都有自己的值类。

然后只需向类中添加generics类型,并使抽象方法接受该类型的参数:

 public abstract class Item { public abstract void use(V v); } 

要使用它,假设MyItem需要一个MyValueClass类型的值对象:

 public class MyItem extends Item { public void use(MyValueClass v) { } } 

如果要用作参数的类型总是可变的,我没有看到使用generics的理由。 只需使用普通对象类型:

 public abstract class Item { public abstract void use(Object ... arguments); } public class Book extends Item { public void use(Object ... arguments) { ... } } 

我能想到的最好的方法是根据use()方法的行为对项目进行分组。

 public abstract class QueueableItem { public abstract void use(String, Queue); } public abstract class OrdinaryItem{ public abstract void use(String); } 

如果分组的项共享一个共同的行为(在相同的方法签名和返回值中很常见),则可以定义和扩展将包含此常见行为定义的父类。

是的,我们可以为抽象方法提供参数,但必须为我们在派生类中编写的实现方法提供相同类型的参数。