在Java中,如果子类具有不同的类型,我可以以某种方式将字段移动到超类吗?

时间:2015-07-26 17:46:28

标签: java field subclass superclass

在我的Java程序中,我有两个非常相似的类,为它们创建一个超类来进行子类化和泛化它们的一些方法会很有意义。

唯一的问题是,其中一个关键字段在一个Queue中实现,一个在PriorityQueue中实现。

有没有办法超类化这些并以某种方式推广字段类型并让子类选择它在实例化时可能会做什么?

public Base{

}

public Sub1{
     Queue<Customer> customers;
}

public Sub2{
     PriorityQueue<Customer> customers;
}

6 个答案:

答案 0 :(得分:1)

priorityqueue是抽象队列的一个子类,它实现了队列,所以基本上可以有一个客户队列。

答案 1 :(得分:1)

您需要做的是将customers的队列作为Base中的依赖项,并让客户端代码决定实例化哪个队列。

public Base{
  private Queue<Customer> customers;

  protected Base(Queue<Customer> customers) {
     this.queue = queue;
  }

}

您不需要Sub1Sub2类,因为它们在使用的队列方面仅与Base不同。客户端代码可以简单地决定使用哪个队列:

Base baseWithQueue = new Base(new ArrayBlockingQueue<Customer>());
Base baseWithPriorityQueue = new Base(new PriorirityQueue<Customer>());

答案 2 :(得分:1)

def path_foto(instance, filename): return 'socios_fotos/' + str(instance.num_socio)+'/' class socio_img (models.Model): num_socio = models.IntegerField() foto = models.ImageField(upload_to=path_foto, default='no-photo.jpg') firma = models.ImageField(upload_to='socios_firmas/', default='no-photo.jpg') 类实现了PriorityQueue接口,因此我建议将Queue作为抽象类并保留Base集合(类型为{{1} }}) 在那里。然后根据需要从customersQueue的构造函数中实例化customers

答案 3 :(得分:1)

是的,因为PriorityQueue实现了Queue。如果要将创建委托给子类,请让它们传递适当的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>());
     }
}

我应该提一下,如果Sub2需要在某些PriorityQueue特定方法中使用特定于Sub2的方法(例如comparator),它可以:

  1. 播放customers(因为它知道customers实际上是PriorityQueue<Customer>,而不仅仅是Queue<Customer>),或

  2. 声明自己的实例字段,该字段将保留输入的引用:

    private PriorityQueue<Customer> priorityCustomers;
    
    Sub2() {
        super(new PriorityQueue<Customer>());
        this.priorityCustomers = (PriorityQueue<Customer>)(this.customers);
    }
    
  3. #2将所需的强制转换保持在最低限度并且很好地包含在构造函数中,以便以后更容易将PriorityQueue<Customer>更改为其他内容。

答案 4 :(得分:1)

是的,如果您将字段实现为Queue,则可以在PriorityQueue中将该字段实例化为Sub2,因为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>());
    }
}

但是,如果您需要在customers内使用PriorityQueue字段作为Queue(而不是Sub2),则需要将其转换为{ {1}}。

答案 5 :(得分:1)

一种解决方案是为您的customers属性提供常规Queue类型,这将为您提供灵活性。但是,如果要在给定的子类中强制执行特定的实现,并在程序的其余部分中携带该信息,则可以使用泛型约束:

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>());
   }
}

这可能很有用,因为它允许您在customers.comparator()内拨打Sub2而无需将customers投射到PriorityQueue