Dog*_*Dog 2 java interface set diamond-problem
我有来自两家公司asoft和bsoft的代码.我也无法改变.这是我的情况的简化版本,我非常确定有足够的信息来查找导致问题的原因.
bsoft提供IGang,代表一个可以与其他帮派作战的团伙.
package bsoft;
public interface IGang {
/** @return negative, 0, or positive, respectively
* if this gang is weaker than, equal to, or stronger
* than the other
*/
public int compareTo(IGang g);
public int getStrength();
public String getName();
public void attack(IGang g);
public void weaken(int amount);
}
Run Code Online (Sandbox Code Playgroud)
asoft提供GangWar,允许IGangs战斗:
package asoft;
import java.util.*;
import bsoft.*;
/** An `IGang` ordered by identity (name) */
public interface ComparableGang extends IGang, Comparable<IGang> {}
package asoft;
import java.util.*;
public class GangWar {
public final Set<ComparableGang> gangs = new TreeSet<ComparableGang>();
public void add(ComparableGang g) {gangs.add(g);}
public void doBattle() {
while (gangs.size() > 1) {
Iterator<ComparableGang> i = gangs.iterator();
ComparableGang g1 = i.next();
ComparableGang g2 = i.next();
System.out.println(g1.getName() + " attacks " + g2.getName());
g1.attack(g2);
if (g2.getStrength() == 0) {
System.out.println(g1.getName() + " smokes " + g2.getName());
gangs.remove(g2);
}
if (g1.getStrength() == 0) {
System.out.println(g2.getName() + " repels " + g1.getName());
gangs.remove(g1);
}
}
for (ComparableGang g : gangs) {
System.out.println(g.getName() + " now controls the turf!");
}
}
}
Run Code Online (Sandbox Code Playgroud)
它需要Gang你提供给它的附加约束Comparable,可能是因为它可以按名称排序或避免重复.每个团伙(以任意顺序,为简单起见,这里使用的设置顺序)攻击另一个团伙,直到只剩下一个团伙(或者没有团伙,如果最后两个团伙有平局).我写了一个简单的实现ComparableGang来测试它:
import asoft.*;
import bsoft.*;
import java.util.*;
class Gang implements ComparableGang {
final String name;
int strength;
public Gang(String name, int strength) {
this.name = name;
this.strength = strength;
}
public String getName() {return name;}
public int getStrength() {return strength;}
public int compareTo(IGang g) {
return strength - g.getStrength();
}
public void weaken(int amount) {
if (strength < amount) strength = 0;
else strength -= amount;
}
public void attack(IGang g) {
int tmp = strength;
weaken(g.getStrength());
g.weaken(tmp);
}
public boolean equals(Object o) {
if (!(o instanceof IGang)) return false;
return name.equals(((IGang)o).getName());
}
}
class Main {
public static void main(String[] args) {
GangWar gw = new GangWar();
gw.add(new Gang("ballas", 2));
gw.add(new Gang("grove street", 9));
gw.add(new Gang("los santos", 8));
gw.add(new Gang("triads", 9));
gw.doBattle();
}
}
Run Code Online (Sandbox Code Playgroud)
测试出来......
$ java Main
ballas attacks los santos
los santos repels ballas
los santos attacks grove street
grove street repels los santos
grove street now controls the turf!
Run Code Online (Sandbox Code Playgroud)
问题是,三合会没有出现在战斗中.事实上,gangs.size()在doBattle()返回3 开始时打印而不是4.为什么?怎么解决?
问题是,三合会没有出现在战斗中.事实上,在doBattle()开头打印gangs.size()会返回3而不是4.为什么?
双方triads并grove street有9强度因此他们来讲等于Gang.compareTo(实现Comparable).因此,只允许一个TreeSet.
如果您不想删除按排序顺序重复的项目,请不要使用TreeSet...
编辑:ComparableGang界面描述表明了预期的内容:
/** An `IGang` ordered by identity (name) */
public interface ComparableGang extends IGang, Comparable<IGang> {}
Run Code Online (Sandbox Code Playgroud)
你的compareTo方法并没有下令"的标识(名称)" -它通过订单强度.说实话,它首先是一个非常愚蠢的界面,因为asoft创建一个类非常容易public class GangNameComparator : Comparator<IGang>,然后如果他们想按名称排序,那么将它作为比较器提供给树集.
但是,因为他们建议你应该实现比较,所以你需要这样做,因为界面描述了:
public int compareTo(IGang g) {
return name.compareTo(g.getName());
}
Run Code Online (Sandbox Code Playgroud)
但是......正如你在评论中注意到的那样(以及Rob的回答中提到的),这与常规命名的IGang描述相矛盾:
public interface IGang {
/** @return negative, 0, or positive, respectively
* if this gang is weaker than, equal to, or stronger
* than the other
*/
public int compareTo(IGang g);
}
Run Code Online (Sandbox Code Playgroud)
实现它既不能ComparableGang满足自己的文档和IGang文档也是不可能的.在asoft的部分,这基本上被设计破坏了.
任何代码应该能够使用IGang实现,知道只有约IGang,依靠以下的实施IGang合同.然而,asoft通过在接口扩展中要求不同的行为来打破这种假设IGang.
这本来是合理的为他们增添了更多的要求的ComparableGang,只要他们没有违反现行的规定IGang.
请注意,这是C#和Java之间的重要区别.在C#中,具有相同签名的两个不同接口中的两个函数可以组合成一个继承它们的接口,并且这两个方法保持不同且可访问.在Java中,这两种方法由于它们是完全抽象的并且具有相同的签名,因此被认为是 相同的方法,并且实现组合接口的类只有一种这样的方法.所以在Java中 ComparableGang是无效的,因为它不能有满足ComparableGang合约和IGang合同的compareTo()实现.
| 归档时间: |
|
| 查看次数: |
417 次 |
| 最近记录: |