Java реализованы методы интерфейса, недоступные из подкласса - PullRequest
0 голосов
/ 30 марта 2020

Описание проблемы:

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

Main.java:5: error: cannot find symbol

This происходит независимо от местоположения пакета, расположения кода (ie: весь код в одном файле или разделение на отдельные файлы *. java) или реализованных методов.

Пример проблемы:

У меня есть 2 класса и интерфейс, A, B и myInterface. Класс A является абстрактным, а B наследуется от A и реализует myInterface. Проблема в том, что когда я запускаю свой код, я не могу вызвать какие-либо методы из реализованного мною интерфейса.

interface myInterface {
  public void printSomething();
}

abstract class A {
  int aVal;

  A() {
    this.aVal = 0;
  }

  public int getVal() {
    return aVal;
  }
}

class B extends A implements myInterface {
  B() {
    super();
  }
}

public void printSomething() {
  System.out.println("Something");
}

class Main {
  public static void main(String[] args) {
    A bObj = new B();

    bObj.printSomething();
    // Throws
    // Main.java:5: error: cannot find symbol
    //       bObj.printSomething();
    //           ^
    // symbol:   method printSomething()
    // location: variable bObj of type A
    // 1 error
  }
}

Для облегчения работы и просмотра у меня также сохранен тот же код, что и выше.

https://repl.it/repls/IdealMobileUserinterface

Почему это происходит, и как бы я go решил проблему? Я поставил себя в тупик и своего учителя, пытающегося понять это.

Ответы [ 3 ]

1 голос
/ 31 марта 2020

Позвольте мне попытаться ответить на этот вопрос канонически.

Вот ваши интерфейсы:

interface iA {
    void fromA();
}
interface iB {
    void fromB();
}

и иерархия классов.

class cX implements iA {
    public void fromX() {}
    public void fromA() {} // to implement iA
}
class cY extends cX implements iB {
    public void fromY() {}
    public void fromB() {} // to implement iB
}

Обратите внимание, что cY также неявно implements iA - он передается от наследования от cX.

Теперь давайте посмотрим, что действительно.

cY cy = new cY();
cy.fromA();  // valid - cY extends cX implements iA
cy.fromB();  // valid - cY implements iB
cy.fromX();  // valid - cY extends cX
cy.fromY();  // valid - cy is a cY

cX cx = new cY(); // valid - cY extends cX
cx.fromA();  // valid - cx implements iA
cx.fromB();  // INVALID - cX does not implement iB. The compiler doesn't know cx is actually a cY instance.
cx.fromX();  // valid - cY extends cX
cx.fromY();  // INVALID - cX is not a cY

iA ia = new cY(); // valid cY extends cX implements iA
ia.fromA();  // valid - fromA() is an iA method
ia.fromB();  // INVALID - iA is not a cY
ia.fromX();  // INVALID - iA does not have that method. Again, compiler doesn't know ia is a cY instance.

Поскольку вы спрашиваете о «полиморфизме» в комментариях: это часть полиморфизма:

iA v = new cY();  // can assign a cY instance to an iA variable
v = new cX();     // can assign a cX instance to an iA variable

Это также причина, по которой вы сейчас не можете назвать v.fromX() или v.fromY(); v также может быть назначен, поэтому доступен только общий знаменатель, а именно методы iA.

1 голос
/ 30 марта 2020

Я считаю, что проблема заключается в том, что вы помещаете все в ссылку на класс A, которая не реализует myInterface и поэтому не обязательно имеет метод printSomething для вызова.

У вас есть объект типа A. И вы пытаетесь вызвать printSomething для него, но типы A не обязательно имеют этот метод. Только те вещи, которые реализуют myInterface, имеют этот метод. Итак, вам нужно указать, что A имеет этот метод.

Или создайте обобщенный метод c, который работает только с типами A, которые реализуют этот интерфейс.

0 голосов
/ 30 марта 2020

Поскольку у вас нет метода printSomething () в классе A, и вы используете ссылку класса A для хранения дочернего объекта B, поэтому по принципу наследования вы не можете получить доступ к дочерним специфицированным c методам, используя родительские ссылки.

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