2013-12-17 3 views
0

У меня есть этотДинамический вызов - Java с интерфейсом и абстрактным классом

public interface ICool { 
    public boolean isCool(); 
} 

Теперь я получил эту иерархию:

public abstract class AbstractCoolness implements ICool{ 
    private isCool; 

    @Override 
    public boolean isCool() { 
     return this.isCool; 
    } 
} 

и

public abstract class CoolPeople extends AbstractCoolness { 
    protected boolean isCool= true; 
} 

и

public abstract class UnCoolPeople extends AbstractCoolness { 
    protected boolean isCool= false; 
}  

Теперь у меня есть много классов, которые наследуют либо UnCoolPeople, либо CoolPeople.

Когда я называю их с помощью этой функции:

if (person instanceof ICool) {  
    if (person.isCool()) { 
     // do something 
    } 
} 

Проблема заключается в том, когда это person.isCool() время вызова он называет abstractCoolness класс и возвращает this.isCool который alwayes ложь.

Любые идеи, почему, когда я использую эту функцию для человека, который простирается от CoolPeople, я все еще получаю isCool() == false?

+1

полиморфизма не относится к переменным экземпляра. –

+0

is_shared;) да спасибо, что вы имеете в виду, не применимо к переменным экземпляра? – Urbanleg

+1

Если вы объявляете поле в подтире, имеющем то же имя, что и поле в супертипе, вы скрываете поле супер-типа. Доступ к полям разрешен в зависимости от типа ссылки, к которой осуществляется доступ к полю. –

ответ

2

Это очень просто. Этот код будет возвращать значение isCool:

public abstract class AbstractCoolness implements ICool{ 
    private isCool; 

    @Override 
    public boolean isCool() { 
     return this.isCool; 
    } 
} 

В то время как этот код будет просто установить новую переменную с именем isCool в подклассе и скрыть базовый элемент, который найден в AbstractCoolness.

public abstract class CoolPeople extends AbstractCoolness { 
    protected boolean isCool= true; 
} 

Метод isCool() всегда будет возвращать isCool переменную, определенную в AbstractCoolness, другой не будет влиять на него. Поскольку default value of a boolean - false, он никогда не вернет true.

Вы можете обойти это, создав конструктор в вашем базовом слое, который принимает логическое значение isCool и передает его через конструктор подкласса.

Очень быстрый эскиз решения:

abstract class AbstractCoolness { 
    private isCool; 

    public AbstractCoolness(bool iscool){ 
    isCool = iscool; 
    } 

    public boolean isCool() { 
     return this.isCool; 
    } 
} 

class CoolPerson extends AbstractCoolness { 
    public CoolPerson() { 
    super(true); 
    } 
} 
1

Вы не можете «переопределить» значение члена.

В вашем коде AbstractCoolness.isCool() возвращает значение его частного члена isCool, который по умолчанию установлен на false.

Вы можете установить isCool в конструктор или переопределить метод isCool() в разных классах, чтобы вернуть ожидаемое значение.

1

Я думаю AbstractCoolness действительно

public abstract class AbstractCoolness implements ICool { 

    private isCool; 

    @Override 
    public boolean isCool() { // Not isShared 
     return this.isCool; 
    } 
} 

В этом случае isCool() возвращает содержимое переменной privateisCool, который инициализируется false. Если бы это было protected и не скрыты (повторно объявлен) подклассами, он будет работать, как вы ожидаете:

AbstractCoolness implements ICool { 
    protected boolean cool; 
    public boolean isCool() { return cool; } 
} 

CoolPerson extends AbstractCoolness { 
    public CoolPerson() { cool = true; } 
} 
+0

Правильно! Даже не знал, что в JLS существует формальное различие. Исправлен мой ответ – Raffaele

Смежные вопросы