Как я могу добавить защищенный метод в класс, реализующий интерфейс в java?

У меня есть класс Property, в котором нет ничего, кроме get-методов. Все поля будут установлены при создании нового экземпляра Property. Property реализует интерфейс под названием IProperty.

Из-за какой-то ошибки в библиотеке, которую я использую, мне приходится заново устанавливать имя экземпляра Property после его создания. Поэтому было предложено создать WrapperPropertyкласс, который будет предоставлять общедоступный setName-метод, который сам вызывает созданный таким образом setName()-метод в Property, который будет защищенным/пакетным представлением.

Проблема в том, что я не могу сделать этот метод защищенным в Property, потому что Eclipse говорит мне добавить его в интерфейс IProperty и сделать общедоступным.

Есть ли обходной путь?

WrapperIPProperty:

public class WrapperIProperty {

    private IProperty prop;

    WrapperIProperty(Property prop) {
        this.prop = prop;
    }

    public void setName(String name) {
        prop.setName(name);
    }
}

Свойство:

public class Property implements IProperty {

    String name;

    protected void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
    public int getFoobar() {
        return 123;
    }
    public int getWhatever() {
        return 987;
    }
}

Имущество:

public interface IProperty {

    public int getWhatever();
    public int getFoobar();
    public String getName();

}

Вот так это выглядит на данный момент. Очевидно, что это не сработает, так как я не могу позволить защитить метод в классе Property. Поэтому мне лучше как-то избавиться от записи interfacee. Но как?


person keinabel    schedule 22.06.2012    source источник
comment
Можем ли мы получить часть кода? Это значительно облегчило бы ответ на ваш вопрос.   -  person arshajii    schedule 22.06.2012
comment
Если ваш класс Property не реализует интерфейс IProperty, вы можете сделать метод setName защищенным.   -  person amicngh    schedule 22.06.2012
comment
Кроме того, я не думаю, что конструктор WrapperIProperty будет работать.   -  person arshajii    schedule 22.06.2012
comment
моя ошибка.. не правильно скопировал. забыл добавить инструменты   -  person keinabel    schedule 22.06.2012
comment
Да ладно, без реализации интерфейса я запутался.   -  person arshajii    schedule 22.06.2012
comment
вы хотите использовать переменную вне области видимости класса, то почему вы хотите сделать ее защищенной? короче говоря, вы хотите использовать общедоступную собственность, но хотите сделать ее защищенной.   -  person maaz    schedule 22.06.2012
comment
@mtariq это вопрос дизайна. В этом классе вообще не должно быть сеттеров, только геттеры. Но так как в библиотеке, которую я использую, есть ошибка, я должен сделать обходной путь, пока они ее не исправят. И по этой причине мне нужен временный метод setName, который не должен быть общедоступным. Доступ к нему должен иметь только обертка, потому что обертка все равно будет удалена после исправления.   -  person keinabel    schedule 22.06.2012
comment
Приведенные вами примеры показывают, что ваш Property всегда имеет общедоступный метод setName, поскольку он реализует IProperty. Но вы утверждаете, что setName только временно. Что тут происходит?   -  person predi    schedule 22.06.2012
comment
Я добавил его в интерфейс в примере, чтобы показать конфликт, чтобы прояснить мою проблему. Кажется, это приводит к недоразумениям, поэтому я удалю это сейчас. Дело принято.   -  person keinabel    schedule 22.06.2012


Ответы (4)


Что вы, вероятно, захотите сделать, так это оставить интерфейс IProperty в покое (не добавляйте к нему метод setName) и создать делегирующий класс-оболочку, который предоставляет нужный вам метод (обертывает реализацию интерфейса).

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

public class WrappedProperty implements IProperty {

    private String name;

    private Property prop;

    WrappedProperty (Property prop) {
        this.prop = prop;
    }

    protected void setName(String name) {
        this.name = name;
    }
    public int getWhatever() {
        return prop.getWhatever();
    }
    public int getFoobar() {
        return prop.getFoobar();
    }    
    public String getName() {
        if (this.name == null) {
           return prop.getName():
        } else {
            return this.name; 
        }
    }
}
public class Property implements IProperty {        

    public String getName() {
        return "blah";
    }
    public int getFoobar() {
        return 123;
    }
    public int getWhatever() {
        return 987;
    }
}
public interface IProperty {

    public int getWhatever();
    public int getFoobar();
    public String getName();

}
person predi    schedule 22.06.2012

Методы в Interface общедоступны, поэтому реализующий класс не может переопределять методы, уменьшая их доступность. Сделай их public

person amicngh    schedule 22.06.2012
comment
Мой вопрос заключался в том, есть ли способ удалить его из интерфейса и, чтобы он был защищен в классе. - person keinabel; 22.06.2012

У вас не может быть общедоступного methodName в интерфейсе и закрытого или защищенного methodName в классе, реализующем этот интерфейс.

Таким образом, вы можете сделать methodName общедоступным в своем классе:

  • этот метод ничего не делает
  • вызов этого метода [another]methodNameProtected (вы даете другое имя новому защищенному методу)

ОБНОВЛЕНИЕ

Если вы хотите, чтобы это было только в интерфейсе, вам нужно изменить свой интерфейс в AbstractClass и поместить в него метод public final returnCode methodName, если метод является общим для всех унаследованных классов.

person cl-r    schedule 22.06.2012
comment
ну, на самом деле это не решает проблему, так как у меня также был бы публичный метод в Property, который изменил бы имя. Единственное место, где я хочу, чтобы метод setName был общедоступным, — это класс WrapperIProperty. - person keinabel; 22.06.2012

Нашел решение этой проблемы:

WrapperIPProperty:

public class WrapperIProperty {

    private Property prop;

    public WrapperIProperty(IProperty prop) {
        this.prop = (Property) prop;
    }

    public void setName(String name) {
        prop.setName(name);
    }

}

Свойство:

public class Property implements IProperty {

    private String name = null;

    [...]

    void setName(String name) {
        this.name = name;
    }
}

Имущество:

public interface IProperty {

    [...]
}

Это сделает работу

person keinabel    schedule 22.06.2012