Methods that return Interface ? [given that there are many implementations of interface]
这个问题可能很简单(我希望不是),但我在一次采访中找到了。
通常,给定一个接口类IntClass,以及许多实现名为ImpIC1,ImpIC2,...,ImpICk的接口的类。 IntClass中的方法是名为void action1(),void action2()...,void actionM()的抽象公共方法。
我得到了一个公共类Test,其公共静态函数名为:public static IntClass foo(IntClass c1,IntClass c2)。此方法对c1和c2执行一些操作以创建InClass并返回。但是,该方法必须适用于IntClass的每个有效实现。问题主要在于c3的定义。我将如何设计方法foo()..
请参阅下面的代码详情:
1 2 3 4 5 | public interface IntClass { abstract void action1(); .. abstract void actionM(); } |
..
1 2 3 4 5 6 | public class ImpIC1 implements IntClass { public void action1() { ... } public void action2() { ....} .. public void actionM() { ... } } |
...
1 2 3 4 5 6 | public class ImpIC2 implements IntClass { public void action1() { ... } public void action2() { ....} .. public void actionM() { ... } } |
...
1 2 3 4 5 6 | public class ImpICk implements IntClass { public void action1() { ... } public void action2() { ....} .. public void actionM() { ... } } |
...
1 2 3 4 5 6 7 | public class Test { public static IntClass foo(IntClass c1, IntClass c2) { .... ... return c3; } } |
...
问题主要在于c3的定义。我尝试了以下解决方案(没有一个工作):
发布的规范非常模糊。"此方法对c1和c2执行一些操作以创建一个InClass并返回"。这根本没有指定任何功能要求。
以下解决方案对c1和c2执行了一些操作(它们是相当荒谬的操作,但规范并不禁止操作无意义)。它还会创建一个返回的新IntClass实例。并且,IntClass的任何实现都可以作为参数传递,并且该方法仍然可以工作。
1 2 3 4 5 6 7 8 9 10 | public static IntClass foo(IntClass c1, IntClass c2){ c1.getClass(); c2.toString(); return new IntClass{ public void action1(){} public void action2(){} ... public void actionM(){} }; } |
现在,基于我对可能需求的猜测,我将提出另一个更明智的解决方案。这并不完全符合规定的要求,但我认为这可能是面试官所寻求的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | public class Test{ public static IntClass foo(IntClass c1, IntClass c2){ return new CompositeIntClass(c1, c2); } public class CompositeIntClass implements IntClass{ private IntClass c1; private IntClass c2; public CompositeIntClass(IntClass c1, IntClass c2){ this.c1 = c1; this.c2 = c2; } public void action1(){ c1.action1(); c2.action1(); } public void action2(){ c1.action2(); c2.action2(); } ... public void actionM(){ c1.actionM(); c2.actionM(); } } } |
使用此实现,调用foo(c1,c2)将正式不对c1或c2执行任何操作。所以它不符合规定的要求。但是,它将创建一个新的IntClass实例,其行为与c1和c2相结合。即在c3上调用action2()将在c1和c2上调用action2()。我认为这可能是要求应该是什么(只是猜测)。
总而言之,这意味着返回的对象(c3)将具有任意IntClass实现的行为。然而,这并不意味着你能够做
解决方案是Composite Pattern的一个示例。
<编辑>
如果使用广义抽象,则必须确保它们与您要用它们解决的问题兼容。由于所描述的问题设置中的所有actionI()方法都具有void返回类型,因此无法提取任何PairInterface实例的最小值和最大值(如注释中所述)。抽象不允许这样做。
如果这是您想要做的,那么解决方案就更简单了。 (这是基于PairInterface包含声明
1 2 3 4 5 6 7 |
除此之外,您还必须创建
注意:
1)如果
2)该方法返回的PairInterface的实现方式无关紧要。具有接口返回类型的原因是接口的任何一致实现都应该起作用。
EDIT>
也许他们想看看你是否知道如何使用反射来返回
1 2 3 4 5 | public IntClass foo(IntClass c1, IntClass c2) { IntClass c3 = c1.getClass().newInstance(); // requires no-arg constructor // use c1 and c2 to set up c3 ... return c3; } |
我不知道你的实施。但这里有一点我们需要知道。
您无法实例化接口(匿名内部类除外)。如果你想让Interface返回更改测试类如下 -
1 2 3 4 5 6 7 8 | public class Test { public static IntClass foo(IntClass c1, IntClass c2,String className) { .... ... IntClass c3 = Class.forName(className); //Set properties of c3 as your logic. return c3; |
}
}
你确定你的问题是对的吗?从你的评论到Eng.Fouad
1 | ImpClass3 s3 = foo(s1, s2) |
这没有意义。在右边有一些抽象的东西,在左边有一些具体的东西是错误的,通常它们反之亦然。这就像你订购"任何吃东西,无论如何"但完全期待"巨无霸鸡肉与可乐":)
您可以使用匿名类创建接口对象并实现所有抽象方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | IntClass c3 = new IntClass() { @Override public void action1() { // ... } // ... @Override public void actionM() { // ... } }; |