返回接口的方法? [鉴于有很多接口实现]

时间:2012-03-18 06:15:07

标签: java oop 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()..

请参阅下面的代码详细信息:

public interface IntClass { 
 abstract void action1(); 
 .. 
 abstract void actionM();
 }

...

 public class ImpIC1 implements IntClass { 
 public void action1() { ... } 
 public void action2() { ....}
 ..
 public void actionM() { ... } 
 } 

...

 public class ImpIC2 implements IntClass { 
 public void action1() { ... } 
 public void action2() { ....}
 ..
 public void actionM() { ... } 
 } 

...

 public class ImpICk implements IntClass { 
 public void action1() { ... } 
 public void action2() { ....}
 ..
 public void actionM() { ... } 
 }    

...

public class Test { 
public static IntClass foo(IntClass c1, IntClass c2) { 
 ....
 ...
  return c3; 
}
} 

...

问题主要在于c3的定义。我尝试了以下解决方案(没有一个工作):

  1. 在foo中,c3被定义为Object的实例..即IntClass c3 =(IntClass)new Object()。 - 编译时错误对象无法强制转换为IntClass
  2. 在foo里面,c3没有初始化。 (编译时错误)。
  3. 在foo中,c3为null,(空指针异常)
  4. 在foo里面,c3被初始化为c3的实现之一(即c3 =(IntClass)new ImpIC1())..问题是如果我们在外部执行ImpIC2 s =(ImpIC1)foo(c1, c2) - 我们收到错误(无法投射)。

5 个答案:

答案 0 :(得分:1)

我不了解您的实施情况。但这里有一点我们需要知道。 您无法实例化接口(匿名内部类除外)。如果您希望Interface返回更改测试类,如下所示 -

     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; 

} }

答案 1 :(得分:1)

也许他们想知道你是否知道如何使用reflection来返回任何类c1的实例。每个对象都是的实例(甚至是匿名内部类)。您可以为引用类型提供接口,但最后它指向实例。

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

答案 2 :(得分:1)

发布的规格非常模糊。 “此方法对c1和c2执行一些操作以创建一个InClass并返回”。这根本没有指定任何功能要求。

以下解决方案对c1和c2执行了一些操作(它们是相当荒谬的操作,但规范并不禁止操作无意义)。它还会创建一个返回的新IntClass实例。并且,IntClass的任何实现都可以作为参数传递,并且该方法仍然有效。

public static IntClass foo(IntClass c1, IntClass c2){
    c1.getClass();
    c2.toString();
    return new IntClass{
            public void action1(){}
            public void action2(){}
            ...
            public void actionM(){}
        };
}

现在,基于我对可能需求的猜测,我将提出另一个更明智的解决方案。这并不完全符合规定的要求,但我认为这可能是面试官所寻求的。

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实现的行为。然而,这并不意味着你能够做SomeArbitraryImplClass c3 = (SomeArbitraryImplClass) foo(c1, c2);,因为这样做会违反界面抽象的整个概念(肯定没有在面试中提倡的内容)。

解决方案是the Composite Pattern的一个例子。

<强>&LT;编辑&gt;

如果您使用广义抽象,则必须确保它们与您打算用它们解决的问题兼容。由于所描述的问题设置中的所有actionI()方法都具有void返回类型,因此无法提取任何PairInterface实例的最小值和最大值(如注释中所述)。抽象不允许这样做。

如果这是您想要做的,那么解决方案就更简单了。 (这是基于PairInterface包含声明int getX()int getY()的假设,这对于PairInterface来说似乎是合理的:)

public class Test{
    public static PairInterface mix(PairInterface c1, PairInterface c2){
        int minX = Math.min(c1.getX(), c2.getX());
        int maxY = Math.max(c1.getY(), c2.getY());
        return new SomePairInterfaceImplementation(minX, maxY);
    }
}

除此之外,您还必须创建SomePairInterfaceImplementation类,或者使用一些可以接受x和y作为构造函数参数的现有类。

请注意:

1)如果PairInterface仅声明void方法,那么计算c1和c2的x值的最大值或最小值是不可能的。这些值被封装和隐藏,无法访问。

2)该方法返回的PairInterface的实现方式无关紧要。具有接口返回类型的原因是接口的任何一致实现都应该有效。

<强>&LT; /编辑&gt;

答案 3 :(得分:0)

您可以使用匿名类创建接口对象并实现所有抽象方法:

IntClass c3 = new IntClass()
{
    @Override
    public void action1()
    {
        // ...
    }

    // ...

    @Override
    public void actionM()
    {
        // ...
    }

};

答案 4 :(得分:0)

你确定你的问题是对的吗?从您对Eng.Fouad的评论

ImpClass3 s3 = foo(s1, s2)

没有意义。在右边有一些抽象的东西,在左边有一些具体的东西是错误的,通常它们反之亦然。这就像你点“任何东西吃,无论如何”,但期待“巨无霸鸡肉与可乐”:)