Дизайн интерфейса Java: интерфейс против логического метода - PullRequest
2 голосов
/ 08 апреля 2011

Я выбираю между следующими 2 дизайнами. Что бы вы порекомендовали и почему?

Я довольно сомневаюсь в размещении методов get / set в интерфейсах во втором методе. Любые комментарии по этому поводу?

public class Foo {
    Time time;
    boolean hasTime();
    Time getTime() { return time; }
    void setTime() { this.time = time; }
}

public class Bar extends Foo {
    boolean hasTime() { return true; }
}

public class Baz extends Foo {
    boolean hasTime() { return false; }
}


main() {
    for (Foo foo : foos) {
        if (foo.hasTime()) {
            // do something
        }
    }
}

против

public class Foo {
}

public class Bar extends Foo implements TimedObject {
    Time time;
    Time getTime() { return time; }
    void setTime() { this.time = time; }
}

public interface TimedObject {
    Time getTime();
    void setTime();
}

main() {
    for (Foo foo : foos) {
        if (foo instance of TimedObject) {
            // do something
        }
    }
}

Ответы [ 4 ]

4 голосов
/ 08 апреля 2011

Второй подход определенно лучше.

В первом подходе геттеры и сеттеры существуют в классах Bar и Baz и могут называться ... независимо от того, что hasTime() возвращает!

Вы можете переопределить метод получения и установки в Baz, чтобы они выдавали (например) исключение OperationNotSupported.Но даже это немного "неприлично":

  • Если вы сравните, как программа будет использовать две версии, первая требует, чтобы вы не забыли вызвать hasTime(), тогда как со второйодин компилятор скажет вам, если вы забудете типизировать тип, совместимый с присваиванием TimedObject.

  • Первая версия нарушает принцип подстановки, потому что Baz будет вести себя несовместимо с его суперклассом Foo.

2 голосов
/ 08 апреля 2011

Я предпочитаю второй, так как реализованные интерфейсы дают вам тип независимо от фактического типа объекта и гарантируют ряд доступных методов («контракт», определенный интерфейсом).

Как правило, не устанавливайте метод boolean hasXX() для свойств, принимаемых пользователем, как обычно, вы должны проверить if (Y.getX() != null), чтобы проверить, установлено ли свойство или имеет какое-либо значение.

1 голос
/ 08 апреля 2011

Мне тоже нравится второй вариант.Более того, если вы сомневаетесь в методах получения и установки интерфейсов, вы всегда можете разделить этот интерфейс на два:

public interface TimedObject {
   Time getTime();
}
public interface MutableTimedObject extends TimedObject {
   void setTime(Time time);
}
...
if (foo instance of TimedObject) {
        // do something
        if (foo instance of MutableTimedObject) {
                // change time
        }
}
0 голосов
/ 08 апреля 2011

Это действительно зависит, если вы спросите меня. Про. с интерфейсом вы сможете переместить этот код в другой класс и применить композицию вместо наследования.

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