методы после расширения абстрактного класса - PullRequest
1 голос
/ 31 января 2012

Я не знаю точно, как описать мою проблему, поэтому приведу пример:

public abstract class A {

  public abstract void methodToOverride();
  public void methodNotToOverride() { }

}

public class B extends A {

  @Override
  public void methodToOverride() { }
  public void someOtherMethodNotFromClassA() { }

}

теперь мне нужно сделать такую ​​вещь в моем коде:

A object = new B();
object.someOtherMethodNotFromClassA();

но я получаю «Не удается разрешить ошибку метода». Определение такого метода в абстрактном классе не вариант. Любая подсказка?

Ответы [ 5 ]

3 голосов
/ 31 января 2012

Это невозможно.В то время как объект имеет тип B, ссылка имеет тип A. Следовательно, вы можете получить доступ только к методам, видимым для класса A.

Если вы измените это:

A a = new B();

наэто:

B a = new B();

вы сможете получить доступ к someOtherMethodNotFromClassA.Другой вариант - привести a к типу B:

A a = new B();
((B)a).someOtherMethodNotFromClassA();
2 голосов
/ 31 января 2012

Несмотря на то, что есть некоторые другие синтаксические ошибки, Оливер Вейлер прав, ссылка относится к типу A, поэтому вы можете получить доступ только к методам типа A.

Если вы приведете его к типу B, то вы также можете получить доступ к методам типа B. Чтобы быть в безопасности, проверьте, действительно ли тип B с instanceof

A clazz = new B();
if (clazz instanceof B)
  ((B)clazz).someOtherMethodNotFromClassA();

Я считаю, что ваш реальный код немного сложнее, поэтому вы можете подумать о приведении ...

И кстати: имя переменной 'class' не будет работать, используйте somethign Different.

1 голос
/ 31 января 2012

У вас есть две проблемы в вашем коде.

Во-первых, вам нужно предоставить реализацию для любых абстрактных методов, чтобы ваш класс был инстанцируемым.Итак, в вашем случае:

@Override
public void methodToOverride(){
// does nothing
}

Во-вторых, и, что более важно, когда вы создаете экземпляр объекта типа A, доступны только методы, относящиеся к A.Поскольку вы определяете new B() как тип A, у вас не будет доступа к методу someOtherMethodNotFromClassA.

Если вы хотите получить к нему доступ, вам нужно либо создать его экземпляр как класс B, либоиспользуйте его как класс B:

B someClass = new B();
someClass.someOtherMethodNotFromClassA();

или

A someClass = new B();
((B)someClass).someOtherMethodNotFromClassA();

Но имейте в виду, что последний вариант довольно уродлив и не прост в обслуживании.

1 голос
/ 31 января 2012

Если вам действительно нужно использовать метод из класса B, а действительно нужно указать, если с помощью абстрактного суперкласса A вы можете использовать:

A clazz = new B();
((B)clazz).someOtherMethodNotFromClassA();

Обратите внимание, что это не очень хорошая практика.

0 голосов
/ 21 июня 2016

Я только что столкнулся с этой проблемой сам, и это ужасно!Как вы должны создавать повторно используемый код, если вы не можете создать подклассы для использования в качестве аргументов?например, в библиотеке:

public abstract class AbstractSetting {
    private boolean property = false;
    public void getProperty() { return property; }
}

public abstract class AbstractFoo {
    protected AbstractSetting setting;

    protected void setSetting(AbstractSetting setting) {
        this.setting = setting;
    }

    public boolean foo() {
        setting.getProperty();
    }
} 

Затем в приложении:

public class Setting extends AbstractSetting {
    private boolean extraProperty = false;
    public void getExtraProperty() { return extraProperty; }
}

public class Foobar extends AbstractFoo {
    public void foobar() {
        setting.getProperty();
        setting.getExtraProperty();   // CAN'T RESOLVE !
    }
}

Foo foo = new Foo();
foo.setSetting(new Setting());
foo.foobar();

Как обойти это?

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