Когда это нормально для абстрактного базового класса иметь (нестатические) члены-данные? - PullRequest
3 голосов
/ 24 мая 2009

Я думаю, название вопроса подводит итог. Есть ли время, когда для ABC было бы неплохо создать элементы данных? Мне было интересно, если есть ситуация, когда это нормально. Единственное, что я могу придумать, - это статичность, и даже тогда это немного натянуто.

Ответы [ 9 ]

4 голосов
/ 24 мая 2009

Я не понимаю, почему ABC не может должным образом иметь элементы данных (например, нестатические) для каждого экземпляра, так как это необходимо для поддержки методов, которые он предоставляет подклассам. Возьмем общий случай, когда ABC существует для предоставления шаблона Template DP (методы ловушки являются абстрактными) - если часть функции метода организационной структуры заключается в обновлении некоторых переменных экземпляра (например, подсчета того, сколько раз метод), то, очевидно, эти переменные также должны быть предоставлены ABC. Можете ли вы объяснить лучше, почему вы думаете, что это плохой дизайн?!

1 голос
/ 24 мая 2009

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

0 голосов
/ 24 мая 2009

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

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

0 голосов
/ 24 мая 2009

Если это состояние используется всеми унаследованными классами, я думаю, обязательно , чтобы переместить его в базовый класс. Хотя база абстрактная. Я думаю, что большинство людей, которые занимаются рефакторингом , согласятся со мной в этом.

Может быть несколько причин, по которым какое-то состояние должно быть в базе. Достаточно веской причиной является сокращение дублирования кода.

Ура!

Редактировать: Скажите, пожалуйста, почему вы отказались от голосования, чтобы я мог улучшить. Спасибо!

0 голосов
/ 24 мая 2009

Я подозреваю, что вы рисуете слишком узкий круг вокруг своей концепции абстрактного базового класса.

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

Многие фреймворки основаны на наследовании. Они почти неизбежно будут иметь абстрактные классы с переменными-членами. Например, DirectShow - это мультимедийная потоковая среда в Windows. Источники, кодеры, декодеры и т. Д. Все реализованы в так называемых «фильтрах». Существуют базовые классы для различных типов фильтров. Каждая из них будет иметь переменные-члены для восходящего и нисходящего фильтров, согласованных типов медиа и т. Д.

0 голосов
/ 24 мая 2009

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

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

Допустим, мы делаем Car абстрактный базовый класс, который имеет заполнители для колес, шасси и двигателя для своих подклассов:

abstract class Car {
    Wheels wheels
    Chassis chassis
    Engine engine

    abstract void accelerate();
    abstract void decelerate();
}

Теперь, для класса, который расширяет Car, члены уже существуют для использования, поэтому подкласс отвечает за заполнение этих переменных-членов:

class NiceCar extends Car {
    Decoration decoration;

    public NiceCar() {
        wheels = new ChromeWheels();
        chassis = new LightweightCompositeChassis();
        engine = new LotsOfHorsepowerEngine();
        decoration = new CoolRacingStripes();
    }

    void accelerate() {
        engine.feedFuel();
    }

    void decelerate() {
        wheels.applyBrakes();
    }
}

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

0 голосов
/ 24 мая 2009

Это ОК , когда ваш член данных в вашем абстрактном классе содержит базовый код для наследования классов

Я бы подумал об использовании интерфейса, когда элемент данных просто для описания вашего класса

0 голосов
/ 24 мая 2009

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

0 голосов
/ 24 мая 2009

Я вижу это в архитектурах плагинов, таких как Paint.NET.

...