Java 接口问题

Java 接口问题,java,interface,Java,Interface,假设我有接口MyInterface和两个实现MyInterface的类A、B。 我声明了两个对象:MyInterface a=new a(),和MyInterface b=new b() 当我试图传递给一个函数-functiondoSomething(a){}时,我得到了一个错误 这是我的代码: public interface MyInterface {} public class A implements MyInterface{} public class B implements M

假设我有接口MyInterface和两个实现MyInterface的类A、B。
我声明了两个对象:
MyInterface a=new a()
,和
MyInterface b=new b()

当我试图传递给一个函数-function
doSomething(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

我不清楚您实际上在问什么,但问题是您没有一个方法接受MyInterface类型的参数。我不知道Java中的确切语法是什么,但是您可以做一些类似于if(b是b){test(b是b)}的事情,但我不会。如果您需要它是泛型的,那么使用MyInterface类型作为变量类型,否则使用B作为变量类型。你正在破坏使用接口的目的。

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

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


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

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

公共类A扩展父类{…}

公共类B扩展父类{…}

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

我认为visitor将在这里帮助您。基本思想是让类(A和B)自己调用适当的方法,而不是试图决定调用哪个方法。作为一名C#guy,我希望我的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");
    }

}

我不确定我是否完全理解这个问题,但似乎有一种方法可以将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()方法并打印结果。但是,从这个问题上,我不能很好地判断您的要求是否使这成为不可能。

听起来您想要的是这样的东西:

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所建议的,添加第二个接口可能是一种方法。注意,您可以在保持二进制兼容性的同时执行此操作。

您有3个选项:

  • 游客模式;您需要能够更改MyInterface类型以包含方法
    visit(Visitor)
    ,其中
    Visitor
    类包含许多用于访问每个子类的方法
  • 在方法内部使用
    if-else
    测试(MyInterface)在它们之间进行检查
  • 使用链接。也就是说,声明处理程序
    ATester
    BTester
    等,所有这些处理程序都实现了接口
    ITester
    ,该接口具有方法
    test(MyInterface)
    。然后在
    ATester
    中,检查类型是否等于A,然后再执行操作。然后,您的主Tester类可以拥有这些测试程序的一个链,并将每个
    MyInterface
    实例向下传递,直到它到达一个可以处理它的
    ITester
    。这基本上将
    if-else
    块从2转换为单独的类

  • 就我个人而言,在大多数情况下我会选择2。Java缺乏真正的面向对象。处理它!提出各种方法通常只会使代码难以理解。

    听起来您需要a)将方法放在MyInterface上,并在a和B中实现多态性,或者B)组合使用复合设计模式和访问者设计模式。当事情变得难以处理时,我会从a)开始,然后朝b)前进

    我对访客的广泛思考:


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

    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)
    。编译器在这里抱怨,因为
    MyInterface
    引用变量可以引用属于
    MyInterface
    子类型的任何对象,但不一定是
    B
    的对象。如果Java中允许,则可能会有运行时错误。举一个例子,让你更清楚地了解这个概念。我已经修改了类
    B
    的代码并添加了一个方法

    public class B implements MyInterface {
        public void onlyBCanInvokeThis() {}
    
    }
    
    现在只需更改
    测试(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()
        }
    }
    

    几乎。应该是:公共无效测试(MyInterface mi)是的,我知道你的方法是有效的,但我确信那是存根代码