4

假设我有接口 MyInterface 和 2 个实现 MyInterface 的类 A、B。
我声明了 2 个对象: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的例子)

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

谢谢

4

10 回答 10

5

你不能只在每个类实现的接口上有一个方法吗?还是您无法控制界面?

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

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

于 2008-09-30T22:39:18.307 回答
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 的建议,添加第二个界面可能是可行的方法。请注意,您可以在保留二进制兼容性的同时执行此操作。

于 2008-09-30T22:44:52.520 回答
2

我不清楚您实际要问什么,但问题是您没有采用 MyInterface 类型参数的方法。我不知道 Java 中的确切语法是什么,但是您可以执行类似 if (b is B) { test(b as B) } 的操作,但我不会。如果需要泛型,则使用 MyInterface 类型作为变量类型,否则使用 B 作为变量类型。你违背了使用界面的目的。

于 2008-09-30T22:38:35.330 回答
1

我认为访问者设计模式会帮助你。基本思想是让你的类(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");
    }

}
于 2008-09-30T22:40:23.873 回答
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() 方法并打印结果。但是,如果您的要求使这成为不可能,我无法从这个问题中完全看出。

于 2008-09-30T22:42:15.880 回答
1

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

于 2012-06-20T09:08:24.023 回答
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 变成单独的类。

在大多数情况下,我个人会选择 2 个。Java 缺乏真正的面向对象。处理它!想出各种方法来解决它通常只会导致难以遵循的代码。

于 2008-09-30T22:48:41.637 回答
0

听起来您需要 a) 通过将方法放在 MyInterface 上并在 A 和 B 中实现来利用多态性,或者 b) 组合和访问者设计模式的某种组合。当事情变得笨拙时,我会从 a) 开始,然后朝着 b) 前进。

我对访客的广泛想法:

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

于 2008-10-01T04:46:16.303 回答
0

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

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

这允许您将 Parent 对象传递给采用 A 或 B 的函数。

于 2008-09-30T22:40:09.663 回答
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()
    }
}
于 2013-05-14T13:42:39.460 回答