[英]In Java, can I somehow move field to superclass if subclasses have different types for them?
In my Java program, I have two classes that are really similar, and it would make a lot of sense to create a superclass for them to subclass and generalize a bunch of their methods. 在我的Java程序中,我有两个真正相似的类,因此为它们创建一个超类以将其子类化并推广一堆方法将非常有意义。
The only problem is that one of their key fields is implemented in one as a Queue
and in one as a PriorityQueue
. 唯一的问题是,它们的关键字段之一是作为
Queue
实现的,而一个字段是PriorityQueue
。
Is there any way to superclass these and somehow generalize the field type and let the subclasses pick what it will perhaps on instantiation? 有什么方法可以超类化这些类并以某种方式泛化字段类型,并让子类选择在实例化时可能会做什么?
public Base{
}
public Sub1{
Queue<Customer> customers;
}
public Sub2{
PriorityQueue<Customer> customers;
}
priorityqueue是实现队列的抽象队列的子类,因此基本队列可以有一个客户队列。
What you need to do is have the queue of customers
as a dependency in Base
and let the client code decide what queue to instantiate. 你需要做的是有排队
customers
作为一个依赖Base
,让客户端代码决定什么排队实例。
public Base{
private Queue<Customer> customers;
protected Base(Queue<Customer> customers) {
this.queue = queue;
}
}
You don't need the Sub1
and Sub2
classes since they only differ from Base
in terms of the queue used. 您不需要
Sub1
和Sub2
类,因为它们仅在使用的队列方面不同于Base
。 Client code can simply decide what queue to use : 客户代码可以简单地决定使用哪个队列:
Base baseWithQueue = new Base(new ArrayBlockingQueue<Customer>());
Base baseWithPriorityQueue = new Base(new PriorirityQueue<Customer>());
The PriorityQueue
class implements the Queue
interface, so I'd recommend making Base
an abstract class and keep the customers
collection (of type Queue
) in there. PriorityQueue
类实现了Queue
接口,所以我建议将Base
作为抽象类,并在其中保留customers
集合( Queue
类型)。 Then instantiate customers
from Sub1
or Sub2
's constructor as appropriate. 然后根据需要从
Sub1
或Sub2
的构造函数实例化customers
。
Yes, since PriorityQueue
implements Queue
. 是的,因为
PriorityQueue
实现了Queue
。 If you want to delegate creation to subclasses, have them pass the appropriate Queue
to use to the base constructor: 如果要将创建委托给子类,请让它们将适当的
Queue
传递给基本构造函数使用:
public class Base {
protected final Queue<Customer> customers;
protected Base(Queue<Customer> c) {
this.customers = c;
}
}
public class Sub1 extends Base {
Sub1() {
super(new WhateverQueue<Customer>());
}
}
public class Sub2 extends Base {
Sub2() {
super(new PriorityQueue<Customer>());
}
}
I should mention that if Sub2
needs to use methods that are specific to PriorityQueue
(such as comparator
) in some Sub2
-specific method, it can either: 我应该提到,如果
Sub2
需要在某些特定于Sub2
方法中使用特定于PriorityQueue
(例如comparator
),则可以:
Cast customers
(since it knows that customers
is actually a PriorityQueue<Customer>
, not just a Queue<Customer>
), or 强制转换
customers
(因为它知道customers
实际上是PriorityQueue<Customer>
,而不仅仅是Queue<Customer>
),或者
Declare its own instance field which will keep the typed reference: 声明自己的实例字段,该实例字段将保留键入的引用:
private PriorityQueue<Customer> priorityCustomers; Sub2() { super(new PriorityQueue<Customer>()); this.priorityCustomers = (PriorityQueue<Customer>)(this.customers); }
#2 keeps the casting required to a minimum and nicely contained to just the constructor, making it easier to change PriorityQueue<Customer>
to something else later. #2使所需的转换保持在最低限度,并且仅包含在构造函数中,可以轻松地将
PriorityQueue<Customer>
更改为其他内容。
Yes, if you implement the field as Queue
, you can instantiate the field as a PriorityQueue
in Sub2
, because PriorityQueue
implements Queue
(source: http://docs.oracle.com/javase/7/docs/api/java/util/PriorityQueue.html ) 是的,如果将字段实现为
Queue
,则可以在Sub2
中将其实例化为PriorityQueue
,因为PriorityQueue
实现了Queue
(来源: http : //docs.oracle.com/javase/7/docs/api/java/util/ PriorityQueue.html )
public Base{
Queue<Customer> customers;
public Base(Queue<Customers> queue){
this.customers = queue;
}
}
public Sub1{
public Sub1(){
super(new Queue<Customer>());
}
}
public Sub2{
public Sub2(){
super(new PriorityQueue<Customer>());
}
}
However, when you need to use the customers
field as a PriorityQueue
(rather than a Queue
) inside Sub2
, you will need to cast it to a PriorityQueue
. 但是,当您需要将
customers
字段用作Sub2
内的PriorityQueue
(而不是Queue
)时,需要将其Sub2
转换为PriorityQueue
。
One solution is to give your customers
attribute the general Queue
type, which will give you flexibility. 一种解决方案是为
customers
属性提供常规的Queue
类型,这将为您提供灵活性。 But if you want to enforce specific implementations in a given subclass, and carry that information in the rest of your program, you can use generic constraints : 但是,如果您想在给定的子类中实施特定的实现,并在程序的其余部分中携带该信息,则可以使用通用约束:
public class Base<Q extends Queue<Customers>> {
protected Q customers;
public Base(Q customers) {
this.customers = customers;
}
}
public Sub1 extends Base<Queue<Customers>> {
public Sub1(Queue<String> customers) {
super(customers);
}
}
public Sub2 extends Base<PriorityQueue<Customers>>{
public Sub2() {
// Sub2 only supports PriorityQueues
super(new PriorityQueue<String>());
}
}
This can be useful, as it allows you to call, say, customers.comparator()
inside Sub2
without having to cast customers
into a PriorityQueue
. 这很有用,因为它允许您在
Sub2
内部调用,例如, customers.comparator()
,而无需将customers
转换为PriorityQueue
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.