界面问题

时间:2008-09-30 22:32:56

标签: java interface

假设我有MyInterface接口和2个实现MyInterface的类A,B 我声明了两个对象:MyInterface a = new A()MyInterface b = new B() 当我尝试传递给函数时 - 函数doSomething(A a){}我收到错误。

这是我的代码:

public interface MyInterface {}

public class A implements MyInterface{}

public class B implements MyInterface{}

public class Tester {

    public static void main(String[] args){
        MyInterface a = new A();
        MyInterface b = new B();
        test(b);
    }

    public static void test(A a){
        System.out.println("A");
    }

    public static void test(B b){
        System.out.println("B");
    }

}

我的问题是我从某个组件界面获取了各种类,我需要为每个类编写函数。
所以一种方法是获取接口并检查它是哪种类型。 (A的例子)

我想知道其他人如何处理这个问题?

THX

10 个答案:

答案 0 :(得分:5)

你能不能在每个类实现的接口上有一个方法?或者你没有控制界面?

这将提供多态性并避免定义任何外部方法。我相信这是一个接口的意图,它允许客户端以非特定类型的方式处理实现它的所有类。

如果无法添加到界面,那么最好使用适当的方法引入第二个界面。如果您无法编辑接口或类,则需要一个以接口作为参数的方法,然后检查具体类。然而,这应该是最后的手段,而是颠覆界面的使用,并将方法与所有实现联系起来。

答案 1 :(得分:3)

听起来你是在追求这样的事情:

public static void test(MyInterface obj){
  if(obj instanceof A) {
     A tmp = (A)obj;
  } else if(obj instanceof B) {
     B tmp = (B)obj;
  } else {
     //handle error condition
  }
}

但请注意,这是非常糟糕的形式,表明您的设计出现了严重错误。如果你没有接口的控制,那么,正如marcj所建议的那样,添加第二个接口可能就好了。请注意,您可以在保持二进制兼容性的同时执行此操作。

答案 2 :(得分:2)

我不清楚你究竟在问什么,但问题是你没有一个采用MyInterface类型参数的方法。我不知道Java中的确切语法是什么,但你可以做一些像if(b是B){test(b as B)}但我不会。如果您需要它是通用的,那么使用MyInterface类型作为变量类型,否则使用B作为变量类型。你打败了使用界面的目的。

答案 3 :(得分:1)

我认为访客design pattern会帮助你。基本的想法是让你的类(A和B)自己调用适当的方法,而不是你试图决定调用哪个方法。作为一名C#人,我希望我的Java能够运作:

public interface Visitable {   
   void accept(Tester tester) 
}

public interface MyInterface implements Visitable {    
}

public class A implements MyInterface{
   public void accept(Tester tester){
       tester.test(this);
   }
}

public class B implements MyInterface{
   public void accept(Tester tester){
       tester.test(this);
   }
}

public class Tester {

    public static void main(String[] args){
        MyInterface a = new A();
        MyInterface b = new B();
        a.accept(this);
        b.accept(this);
    }

    public void test(A a){
        System.out.println("A");
    }

    public void test(B b){
        System.out.println("B");
    }

}

答案 4 :(得分:1)

我不确定我是否完全理解这个问题,但似乎有一种方法可以将test()方法移到子类中:

public interface MyInterface {    
    public void test();
}

public class A implements MyInterface{
    public void test() {
        System.out.println("A");
    }
}

public class B implements MyInterface{
    public void test() {
        System.out.println("B");
    }
}

public class Tester {

    public static void main(String[] args){
        MyInterface a = new A();
        MyInterface b = new B();
        b.test();
    }
}

您可以类似地使用toString()方法并打印出结果。但是,如果你的要求不可能,我无法从这个问题中说出来。

答案 5 :(得分:1)

在一个.java文件中只使用一个公共类/接口,否则会抛出错误。并使用对象名称调用对象..您仅在Teater类中声明了两个方法,然后声明类A,B的目的是什么。

答案 6 :(得分:0)

我通常使用抽象类来解决这个问题,如下所示:

  

public abstract class Parent {}
  public class A extends Parent {...}
  public class B extends Parent {...}

允许您将Parent对象传递给带有A或B的函数。

答案 7 :(得分:0)

您有3个选项:

  1. 访客模式;您需要能够更改MyInterface类型以包含方法visit(Visitor),其中Visitor类包含许多访问每个子类的方法。
  2. 在方法if-else中使用test(MyInterface)进行检查
  3. 使用链接。也就是说,声明处理程序ATesterBTester等,所有这些都实现了具有方法ITester的接口test(MyInterface)。然后在ATester中,在执行操作之前检查类型是否等于A.然后,您的主Tester类可以拥有一组这些测试人员,并将每个MyInterface实例传递到链中,直到它到达可以处理它的ITester。这基本上是将if-else块从2转变为单独的类。
  4. 就个人而言,在大多数情况下我会选择2。 Java缺乏真正的面向对象。处理它!提出各种各样的方法通常只会导致难以理解的代码。

答案 8 :(得分:0)

听起来你需要a)通过在MyInterface上放置方法并在A和B中实现或b)Composite和Visitor设计模式的某种组合来利用多态性。我开始a)并且当事情变得笨拙时前往b)。

我对访客的广泛想法:

http://tech.puredanger.com/2007/07/16/visitor/

答案 9 :(得分:0)

public interface MyInterface {}

public class A implements MyInterface{}

public class B implements MyInterface{}

public class Tester {

    public static void main(String[] args){
       MyInterface a = new A();
       MyInterface b = new B();
       test(b); // this is wrong
    }

    public static void test(A a){
        System.out.println("A");
    }

    public static void test(B b){
        System.out.println("B");
    }

}

您正在尝试将MyInterface引用变量引用的对象传递给使用其子类型为test(B b)的参数定义的方法。编译器在这里抱怨,因为MyInterface引用变量可以引用任何MyInterface子类型的对象,但不一定是B的对象。如果允许,则可能存在运行时错误Java的。举个例子,让你的概念更清晰。我修改了类B的代码并添加了一个方法。

public class B implements MyInterface {
    public void onlyBCanInvokeThis() {}

}

现在只需更改test(B b)方法,如下所示:

public static void test(B b){
    b.onlyBCanInvokeThis();
    System.out.println("B");
}

如果编译器允许,此代码将在运行时爆炸:

 MyInterface a = new A();
 // since a is of type A. invoking onlyBCanInvokeThis()
 // inside test() method on a will throw exception.
 test(a); 

为防止这种情况,编译器不允许使用超类引用的此类方法调用技术。


我不确定你想要实现什么,但似乎你想要实现运行时多态性。为此,您需要在MyInterface中声明一个方法,并在每个子类中实现它。这样,对方法的调用将在运行时根据对象类型而不是引用类型进行解析。

public interface MyInterface {    
    public void test();
}

public class A implements MyInterface{
    public void test() {
        System.out.println("A");
    }
}

public class B implements MyInterface{
    public void test() {
        System.out.println("B");
    }
}

public class Tester {

    public static void main(String[] args){
        MyInterface a = new A();
        MyInterface b = new B();
        b.test(); // calls B's implementation of test()
    }
}