Метод интерфейса, ссылающийся на конкретный класс в качестве параметра, вызывает связь?

Я думал о программировании для интерфейсов, а не для конкретных классов, но у меня было сомнение: должен ли какой-либо метод интерфейса содержать ссылки на конкретные классы?

Предположим, следующие сценарии:

1)

public interface AbsType1 {
    public boolean method1(int a); // it's ok, only primitive types here
}

2)

public interface AbsType2 {
    public boolean method2(MyClass a); // I think I have some coupling here
}

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

public interface MyInterface {} // yes, this is empty

public classe MyClass implements MyInterface {
    // basically identical to the previous "MyClass"
}


public interface AbsType2 {
    public boolean method2(MyInterface a); // this is better (as long as the
                                           // interface is really stable)
}

Но есть еще кое-что, что не убеждает меня... Мне неудобно объявлять пустой интерфейс, хотя я видел, что кто-то другой делает это. Может, и Abstract Class будет работать лучше здесь?

Я немного смущен.

РЕДАКТИРОВАТЬ:

Хорошо, я попытаюсь быть более конкретным, приведя пример. Допустим, я определяю ShopCart и хочу, конечно, добавить товары в корзину:

public interface ShopCart {
    public void addArticle(Article a);
}

Теперь, если Article - это конкретный класс, что если его реализация со временем изменится? Вот почему я мог бы подумать о том, чтобы сделать его Интерфейсом, но, опять же, он, вероятно, не подходит, по крайней мере, на семантическом уровне, потому что интерфейсы должны определять поведение, а у Статьи нет (или почти нет... Я думаю, это своего рода сущность учебный класс).

Так что, вероятно, я сейчас прихожу к выводу, что лучше сделать Article абстрактным классом в этом случае... что вы думаете об этом?

3 ответа

Я бы использовал интерфейсы, потому что композиция намного лучше, чем наследование. "Должен ли какой-либо интерфейсный метод содержать ссылки на конкретные классы?", Почему не должен? Некоторые классы в пакете связаны, это факт и метод общего пользования. Когда вы пометили это отношение в интерфейсе, вы увидите, от каких классов зависит ваша реализация. Отношения зависимости или композиции не являются наследованием, поэтому они должны избегать абстрактного класса.

По моему мнению Interfaces подходят для всех типов, где реализация может отличаться. Но если вы определите module который вводит новый тип, который не предназначен для альтернативных реализаций, тогда нет необходимости определять его как Interface на первом месте. Часто это было бы чрезмерным дизайном, по моему мнению. Это зависит от проблемной области и часто от того, как поддерживают тестирование или AOP-ткачество.

Например, рассмотрим двухмерную проблемную область, в которой необходимо смоделировать Location как тип. Если ясно, что Location всегда представлен x а также y координаты, вы можете предоставить его как Class, Но если вы не знаете, какие свойства Location может иметь (данные GPS, координаты x, y, z и т. д.), но вы полагаетесь на некоторое поведение, как distance()вместо этого вы должны смоделировать его как интерфейс.

Если нет открытых методов, которые AbsType будет доступ в MyClass тогда пустой интерфейс, вероятно, не очень хороший путь.

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

Так что если AbsType не собирается использовать какие-либо методы из MyClass / MyInterface, тогда я предполагаю, что это в основном только сохранение объекта класса для какой-то другой цели. В этом случае рассмотрите использование дженериков, чтобы прояснить, как вы хотите AbsType использоваться без привязки к коду клиента, например

public class AbsType3<C extends Class<?>> {

  public boolean method3(T classType) {...}

}

Затем вы можете ограничить типы классов, чтобы разрешить, если это необходимо, путем обмена <C extends Class<?>> параметр типа для чего-то другого, который также может быть интерфейсом, например <C extends Class<Collection<?>>>,

Пустые интерфейсы чем-то похожи на логические флаги для классов: либо класс реализует интерфейс (true), либо нет (false). Если вообще, эти маркерные интерфейсы должны использоваться для передачи важного утверждения о том, как класс должен (или не должен) использоваться, см. Serializable например.

Другие вопросы по тегам