Можно ли использовать одно и то же определение интерфейса, но обеспечить другое поведение? - PullRequest
0 голосов
/ 03 марта 2009

Суть моего вопроса такова: «У меня есть 2 класса, которые имеют общий интерфейс, однако эти два класса имеют разное поведение в отношении своих свойств. Один интерфейс выдает исключение, если значения параметров недопустимы, другой обновляет свое внутреннее состояние для обработки недопустимых значений. Допустимо ли, чтобы два класса совместно использовали один и тот же интерфейс, или должны быть определены два интерфейса, чтобы указать разработчику, что оба имеют разное поведение? "

Я постараюсь уточнить с некоторым кодом. У меня есть интерфейс определения ниже.

public interface IStationDictionary
{
    bool this[string stationId] { get; set; }
}

И класс, реализующий интерфейс, этот класс используется для установки выходного порта на плате цифрового ввода-вывода.

public class DigitalStationAdapter : IStationDictionary
{
    public bool this[string stationId]
    {
        get { return ports[stationId].Value; }
        set { ports[stationId].Value = value; }
    }

    public void AddDigitalStation(string stationId, DigitalIoPort port)
    {
        ports.Add(stationId, port);
    }

    private IDictionary<string, DigitalIoPort> ports = new Dictionary<string, DigitalIoPort>();
}

У меня также есть классы, которые записывают, какие станции изменили значения, чтобы эти изменения можно было распространить на цифровой ввод-вывод.

public class StationTransitions : IStationDictionary
{
    public bool this[string stationId]
    {
        get
        {
            bool result = false;

            if(changes.ContainsKey(stationId))
                result = changes[stationId];

            return result;
        }
        set
        {
            if(!changes.ContainsKey(stationId))
                changes.Add(stationId, value);
            else
                changes[stationId] = value;
        }
    }

    public IDictionary GetChanges()
    {
        IDictionary<string, bool> result = changes;

        changes = new Dictionary<string, bool>

        return result;
    }

    private IDictionary<string, bool> changes = new Dictionary<string, bool>();
}

Таким образом, хотя оба класса реализуют один и тот же интерфейс, DigitalStationAdapter сгенерирует исключение KeyNotFoundException, если вы попытаетесь получить доступ к индексатору с StationId, отсутствующим в словаре. Принимая во внимание, что StationTransitions будет успешным, то есть другим поведением. Это нормально, я думал, что интерфейсы используются для определения поведения, а также структуры?

Кит.

1 Ответ

2 голосов
/ 03 марта 2009

Это нормально. Подумайте об этом следующим образом: ключом к определению того, является ли какое-либо отношение наследования "в порядке", является принцип замены Лискова. Это требует, чтобы код, ожидающий базовый класс, мог использовать производный класс, не зная его. Это подразумевает, что предварительные условия для метода не могут быть усилены в производном классе, но могут быть ослаблены. Интерфейсы - это особый случай базовых классов.

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

С другой стороны, если вы создадите класс, который автоматически обрабатывает недопустимый ввод без базового класса, и создадите класс, который выбрасывает потомка, это было бы плохо, потому что код ожидает базовый класс не может использовать производный класс, как если бы это был базовый класс. Он должен знать о производном классе, чтобы иметь дело с возможным исключением.

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