привести объект к интерфейсу в Java? - PullRequest
12 голосов
/ 07 декабря 2011

если мы приведем объект к интерфейсу, не сможет ли этот объект вызывать свои собственные методы?в следующем примере myObj сможет вызывать только методы MyInterface?

MyInterface myObj = new Obj();

Если это правильно, в чем разница между этими двумя объектами:

MyInterface myObj = new Obj();

MyInterface mySec = new Sec();

Спасибоза вашу помощь

Ответы [ 8 ]

18 голосов
/ 07 декабря 2011
MyInterface myObj = new Obj(); 
MyInterface mySec = new Sec(); 

Для того, чтобы это было законно, оба Obj и Sec должны быть реализациями MyInterface.Разница между этими двумя объектами будет как они обеспечивают эту реализацию.Obj и Sec могут делать две очень разные или очень похожие вещи, но их общность заключается в том, что они будут придерживаться контракта, на который вы могли бы положиться.Предположим, у вас есть метод

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

Каждый объект, myObj и mySec, может быть передан в этот метод, и этот метод может затем использовать метод frob этого объекта (предполагая, что frob является частьюобъявление интерфейса).Это освобождение .Это позволяет вам делать очень мощные вещи, программируя для интерфейсов, а не для реализаций.Например, вы можете расширить функциональность классов и не изменять строку кода в этих классах, вы просто пропускаете другую реализацию зависимости.Вы не связаны или не связаны с каким-либо одним внедрением внутри метода doSomethingWith.

, но я также прочитал, что если мы объявим объект myObj как MyInterface, myObjне сможет использовать свои собственные методы (из класса Obj), верно ли это

Внутренне, экземпляры Obj будут по-прежнему иметь полный доступ к Obj API.myObj по-прежнему Obj, он всегда сможет использовать свои собственные детали реализации.

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

Экземпляры Obj по-прежнему будут экземплярами Obj, и эти экземпляры по-прежнему смогут использовать doFrobbing.Внешне пользователи , использующие эти экземпляры через ссылку на интерфейс, смогут получить доступ только к методам интерфейса.

1 голос
/ 07 декабря 2011
MyInterface myObj = new Obj();
MyInterface mySec = new Sec();

Вы объявляете экземпляр MyInterface с именем myObj. Вы инициализируете это с новым Obj (); который авторизуется компилятором, если Obj реализует MyInterface. Очевидно, что myObj может вызывать только методы MyInterface. То же самое для второй строки.

Вот пример кода, чтобы попробовать:

public class Test {

    public static void main(String args[]){
          A a = new A();
          a.say();
          a.a();

          B b = new B();
          b.say();
          b.b();

          I ia = new A();
          ia.say();
          ia.a(); // fail
    }

}

interface i {
    public void say();
}

class A implements i {
    public void say(){
        System.out.println("class A");
    }
    public void a(){
        System.out.println("method a");
    }
}

class B implements i {
    public void say(){
        System.out.println("class B");
    }
    public void b(){
        System.out.println("method b");
    }
}
1 голос
/ 07 декабря 2011

Разницы нет. Вы сможете вызывать MyInterface методы интерфейса только для myObj и mySec. Очевидно, ваш код будет компилироваться, только если Obj и Sec реализуют интерфейс Myinterface.

1 голос
/ 07 декабря 2011

Только методы в интерфейсе видимы , но все методы в объекте все еще могут быть вызваны, если они становятся доступными в противном случае.Например:

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

В вышеупомянутых случаях и Obj, и Sec могут вызывать своих закрытых членов, даже если они не будут видны в других классах.Поэтому, когда вы говорите ...

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

... как вы задали в вопросе, в то время как верно, что в myObj и mySec единственным видимым методом является getName(),их базовая реализация может отличаться.

0 голосов
/ 05 марта 2015

Простая аналогия:

Рассмотрим шеф-повара (интерфейс).И есть китайский повар (классы) и американский повар (классы).В настоящее время есть гостиница, которая собирается нанять шеф-повара на основе некоторых критериев, таких как

  • может готовить без вегетарианцев
  • может готовить вегетарианцев
  • имеет опыт работыиз 5 лет

Здесь право - это контекст, в котором оценивается человек типа шеф-повара (функциональность типов).Теперь могут быть случаи, когда китайский шеф-повар может также готовить морепродукты, итальянские блюда и т. Д., Как и в случае с американским коллегой.Все это может показаться неуместным руководителю отеля, так как его интересуют только требуемые критерии.

Работа шеф-повара в отеле аналогична объекту типа шеф-повара, который используется в коде.Очевидная работа будет заключаться в приготовлении вегетарианской и не вегетерианской пищи (критерии или методы сопряжения).Это не означает, что отель не может использовать навыки приготовления морепродуктов китайского шеф-повара.

Нужно только указать, какие навыки (функциональность) отель ищет.

Надеюсь, вы получитеидея.

0 голосов
/ 07 декабря 2011

Изменение типа переменной (т.е. ссылки) не меняет сам объект. Объект всегда может вызывать свои собственные методы, независимо от того, какие типы объявленных переменных ссылаются на него.

0 голосов
/ 07 декабря 2011
MyInterface mi = new Obj();
mi.getInterfaceMethods(); (methods in the MyInterface)

if(mi instanceof Obj) {
     mi.getObjMethods(); (methods in the Obj)
}
0 голосов
/ 07 декабря 2011

В коде, который вы показали, вы никогда не выполняете каст.

Типичным использованием интерфейса является определение некоторых методов, которые будут доступны, не заботясь о конкретной реализации.

Хорошим примером этого являются слушатели в стандартном JDK.Например, PropertyChangeListener.Это интерфейс, который определяет метод, который может быть вызван при изменении свойства.Типичное использование этого интерфейса - присоединение его к классу, у которого есть свойства, и этот класс будет предупреждать тех слушателей, когда одно из его свойств изменилось.

Классу все равно, что будут делать эти слушатели.Он опирается только на тот факт, что этот метод propertyChange будет присутствовать, и вызывает этот метод.

Класс может вызывать этот метод только на приемнике, поскольку он знает только о методе, определенном в интерфейсе.Если у этих слушателей есть другие методы, они могут сами вызывать эти методы, но это только потому, что они знают, что они больше, чем интерфейс.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...