![](/img/trans.png)
[英]Generics - how to define a method that takes only classes that implement a particular interface
[英]How to define/implement this interface with generics in a simpler way?
我正在研究遗传算法,我希望它尽可能抽象,以便能够重用GA。 我定义并实现了一个人口接口,并且很好地工作了,但是我敢肯定这不是最好的方法。 我没有Java泛型的丰富经验。 有没有更简单的方法来定义和实现人口接口(例如,避免强制转换?避免在getChromosomes()中使用新列表?)
public interface Population
{
void addChromosomes(List<? extends Chromosome> chromosomes);
List<Chromosome> getChromosomes();
// More code here ...
}
public class TSPPopulation implements Population
{
private List<TSPChromosome> chromosomes;
@Override
public void addChromosomes(List<? extends Chromosome> chromosomes) {
for (Chromosome chromosome : chromosomes) {
this.chromosomes.add((TSPChromosome) chromosome);
}
}
@Override
public List<Chromosome> getChromosomes() {
List<Chromosome> newList = new ArrayList<Chromosome>();
for (TSPChromosome chromosome : chromosomes) {
newList.add(chromosome);
}
return newList;
}
}
在界面中使用有界通配符:
public interface Population<T extends Chromosome>{
void addChromosomes(List<T> chromosomes);
List<T> getChromosomes();
}
public class TSPPopulation implements Population<TSPChromosome>
{
private List<TSPChromosome> chromosomes;
@Override
public void addChromosomes(List<TSPChromosome> chromosomes) {
...
}
@Override
public List<TSPChromosome> getChromosomes() {
...
}
}
最简单的解决方案是扩展列表(然后使用addAll(...)
将Chromosoms列表添加到列表中):
class Population<T extends Chromosome> extends ArrayList<T> {
}
但是,如果您想要相同的结构,则可以将“ Population
变成一个通用列表类。 这样,可以在通用基类中处理add...
和get...
方法。 如果您确实想覆盖任何其他功能,则只需扩展Population
( class TSPPopulation extends Population<TSPChromosome>
。
用法:
public static void main(String... args) {
Population<TSPChromosome> tspPopulation = new Population<TSPChromosome>();
...
}
实现方式:
class Population<T extends Chromosome> {
private List<T> chromosomes = new ArrayList<T>();
public void addChromosomes(List<T> chromosomes) {
this.chromosomes.addAll(chromosomes);
}
public List<T> getChromosomes() {
return new ArrayList<T>(this.chromosomes);
}
}
如果您将“人口”设为通用,那将更加安全:
public interface Population<T extends Chromosome> {
void addChromosomes(List<T> chromosomes);
List<T> getChromosomes();
}
public class TspPopulation implements Population<TspChromosome>{
@Override
public void addChromosomes(List<TspChromosome> chromosomes){
//
}
@Override
public List<TspChromosome> getChromosomes(){
//
}
}
这样,您就不需要在客户端代码中进行任何强制转换。
我知道GA,并且我会问您的“ Population
实施方案是否实际上需要知道您所放入的哪种Chromosome
。根据“ Chromosome
子类,您是否真的有不同的“ Population
实施方案? 或者,您真正想要的是确保Population
具有相同的Chromosome
子类? 在后一种情况下,您可以按照其他建议的方式定义“ Population
接口,并进行通用实现(或完全跳过该接口):
public class PopulationImpl implements Population<T extends Chromosome> {
private List<T> chromosomes;
@Override
public void addChromosomes(List<T> chromosomes) {
this.chromosomes.addAll(chromosomes);
}
@Override
public List<T> getChromosomes() {
return new ArrayList<T>(chromosomes);
}
}
注意不要放置太多的泛型,否则最终将导致泛型地狱,或大量的强制转换,这将使泛型变得更烦人而不是有用。
是的,例如:
public interface Population<T extends Chromosome>
{
void addChromosomes(List<T> chromosomes);
List<T> getChromosomes();
// More code here ...
}
public class TSPPopulation implements Population<TSPChromosome>
{
private List<TSPChromosome> chromosomes;
@Override
public void addChromosomes(List<TSPChromosome> chromosomes) {
this.chromosomes.addAll(chromosomes);
}
@Override
public List<TSPChromosome> getChromosomes() {
return new ArrayList<TSPChromosome>(chromosomes);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.