在java中将对象强制转换为接口?

2022-09-03 18:29:30

如果我们将一个对象强制转换为接口,这个对象不能调用自己的方法吗?在下面的示例中,将只能调用 MyInterface 方法吗?myObj

MyInterface myObj = new Obj();

如果这是正确的,那么这两个对象之间的区别是什么:

MyInterface myObj = new Obj();

MyInterface mySec = new Sec();

感谢您的帮助


答案 1
MyInterface myObj = new Obj(); 
MyInterface mySec = new Sec(); 

要使这合法化,两者都必须是 的实现者。这两个对象之间的区别在于它们如何提供该实现。 并且可以做两件非常不同或非常相似的事情,但它们的共同点是它们会遵守您可以依赖的合同。考虑你有一个方法ObjSecMyInterfaceObjSec

public void doSomethingWith(MyInterface thing) {
     thing.frob();
}

每个对象 和 都可以传递到此方法中,然后此方法可以使用该对象的方法(假设 frob 是接口声明的一部分)。这是解放。这允许您通过编程到接口而不是实现来做非常强大的事情。例如,您可以扩展类的功能,而不必更改这些类中的一行代码,只需传递依赖项的不同实现即可。您没有绑定或耦合,该方法中的任何一个暗示。myObjmySecfrobdoSomethingWith

但我也读到,如果我们将对象myObj声明为MyInterface,myObj将无法使用自己的方法(来自Obj类),这是正确的

在内部,的实例将继续具有对 API 的完全访问权限。 仍然是一个,它将始终能够使用自己的实现细节。ObjObjmyObjObj

public interface MyInterface {
    void frob();
}

public class Obj implements MyInterface {

    public void frob() {
        doFrobbing();
    }

    private void doFrobbing() {
        System.out.println("frobbing");
    }

    public static void main(String[] args) {
        MyInterface myObj = new Obj();
        myObj.frob(); // still internally calls doFrobbing()
        ((Obj)myObj).doFrobbing(); // visible only via class reference
    }
}

的实例仍将是 的实例,并且这些实例仍将能够使用 。在外部,通过接口引用使用这些实例的用户只能访问接口方法。ObjObjdoFrobbing


答案 2

只有接口中的方法可见,但对象中的所有方法仍然可以被调用,只要它们以其他方式可访问即可。例如:

public interface MyInterface {
    String getName();
}

public class Obj implements MyInterface {
    private String getFirstName() {
        return "John";
    }

    private String getLastName() {
        return "Doe";
    }

    @Override
    public String getName() {
        return getFirstName() + " " + getLastName();
    }
}

public class Sec implements MyInterface {
    private String getDate() {
        return new Date().toString();
    }

    @Override
    public String getName() {
        return getDate();
    }
}

在上述情况下,两者都可以调用其私有成员,即使它们在其他类中不可见。所以当你说...ObjSec

MyInterface myObj = new Obj();
MyInterface mySec = new Sec();

...正如您在问题中所问的,虽然确实在和唯一可见的方法是,它们的基础实现可能不同。myObjmySecgetName()