在英语中,同形异义词对是具有相同拼写但不同含义的两个单词。
在软件工程中,一对单应性方法是名称相同但要求不同的两种方法。让我们看一个人为的示例,以使问题尽可能清楚:
interface I1 {
/** return 1 */
int f()
}
interface I2 {
/** return 2*/
int f()
}
interface I12 extends I1, I2 {}
我该如何实施I12
? C# 有办法 https://stackoverflow.com/questions/4103300/c-sharp-why-implement-interface-explicitly这样做,但 Java 没有。所以唯一的解决办法就是破解。如何通过反射/字节码技巧/等来完成最可靠(即它不一定是一个完美的解决方案,我只想要最有效的解决方案)?
请注意,我无法合法地进行逆向工程的一些现有闭源大量遗留代码需要类型参数I12
并代表I12
两者都具有的代码I1
作为参数,并且代码具有I2
作为参数。所以基本上我需要做一个实例I12
知道什么时候它应该充当I1
以及何时应充当I2
,我相信可以通过在运行时查看字节码 https://stackoverflow.com/questions/2737285/is-there-a-way-to-obtain-the-bytecode-for-a-class-at-runtime直接呼叫者的。我们可以假设调用者没有使用反射,因为这是简单的代码。问题是作者I12
没想到Java合并了f
来自两个界面,所以现在我必须想出解决该问题的最佳方法。没有任何召唤I12.f
(显然,如果作者编写了一些实际调用的代码I12.f
,他会在出售之前注意到这个问题)。
请注意,我实际上是在寻找这个问题的答案,而不是如何重组我无法更改的代码。我正在寻找可能的最佳启发式方法或精确的解决方案(如果存在)。请参阅格雷的答案以获得有效的示例(我确信有更强大的解决方案)。
Here https://stackoverflow.com/questions/15795058/triads-not-showing-up-to-fight-java-set-missing-an-item是两个接口中单应性方法问题如何发生的具体示例。这是另一个具体的例子:
我有以下 6 个简单的类/接口。它类似于围绕剧院和在其中表演的艺术家的商业活动。为了简单和具体,我们假设它们都是由不同的人创建的。
Set
表示一个集合,如集合论中:
interface Set {
/** Complements this set,
i.e: all elements in the set are removed,
and all other elements in the universe are added. */
public void complement();
/** Remove an arbitrary element from the set */
public void remove();
public boolean empty();
}
HRDepartment
uses Set
代表员工。它使用复杂的流程来解码要雇用/解雇哪些员工:
import java.util.Random;
class HRDepartment {
private Random random = new Random();
private Set employees;
public HRDepartment(Set employees) {
this.employees = employees;
}
public void doHiringAndLayingoffProcess() {
if (random.nextBoolean())
employees.complement();
else
employees.remove();
if (employees.empty())
employees.complement();
}
}
一个的宇宙Set
的雇员可能是已向雇主提出申请的雇员。所以当complement
当该集合被调用时,所有现有员工都会被解雇,而之前申请的所有其他员工都会被雇用。
Artist
代表艺术家,例如音乐家或演员。艺术家有自我。当别人称赞他时,他的自我意识就会增强:
interface Artist {
/** Complements the artist. Increases ego. */
public void complement();
public int getEgo();
}
Theater
使Artist
执行,这可能会导致Artist
待补充。剧院的观众可以在表演之间评判艺术家。表演者的自我意识越高,观众就越可能喜欢他的表演。Artist
,但如果自我超越某一点,艺术家就会被观众负面看待:
import java.util.Random;
public class Theater {
private Artist artist;
private Random random = new Random();
public Theater(Artist artist) {
this.artist = artist;
}
public void perform() {
if (random.nextBoolean())
artist.complement();
}
public boolean judge() {
int ego = artist.getEgo();
if (ego > 10)
return false;
return (ego - random.nextInt(15) > 0);
}
}
ArtistSet
简单来说就是一个Artist
and a Set
:
/** A set of associated artists, e.g: a band. */
interface ArtistSet extends Set, Artist {
}
TheaterManager
主持节目。如果剧院的观众对艺术家有负面评价,剧院会与人力资源部门沟通,人力资源部门将解雇艺术家、雇用新艺术家等:
class TheaterManager {
private Theater theater;
private HRDepartment hr;
public TheaterManager(ArtistSet artists) {
this.theater = new Theater(artists);
this.hr = new HRDepartment(artists);
}
public void runShow() {
theater.perform();
if (!theater.judge()) {
hr.doHiringAndLayingoffProcess();
}
}
}
一旦你尝试实施一个ArtistSet
:两个超级接口都指定complement
应该做其他事情,所以你必须实现两个complement
不知何故,在同一个类中具有相同签名的方法。Artist.complement
是一个同形异义词Set.complement
.