Подтвердить что ты не робот

Наследовать от класса или абстрактного класса

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

4b9b3361

Ответ 1

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

Ответ 2

Если базовый класс не должен быть создан, сделайте его абстрактным классом - если базовый класс должен быть создан, то не делайте его абстрактным.

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

abstract class WritingImplement
{
    public abstract void Write();
}

class Pencil : WritingImplement
{
    public override void Write() { }
}

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

class Dog
{
    public virtual void Bark() { }
}

class GoldenRetriever : Dog
{
    public override void Bark() { }
}

Все это довольно субъективно - вы должны быть в состоянии сделать довольно хороший суждение, основанный на потребностях вашего конкретного домена.

Ответ 3

Это зависит от того, имеет ли смысл, чтобы рассматриваемый базовый класс существовал на нем, не будучи полученным? Если ответ "да", то он должен быть обычным классом, иначе он должен быть абстрактным классом.

Ответ 4

Я предлагаю:

  • Создайте интерфейс.
  • Внедрить интерфейс в базовом классе.
  • Сделать базовый класс реальным классом, а не абстрактным (см. ниже почему).

Причина, по которой я предпочитаю реальные классы вместо абстрактных классов, заключается в том, что абстрактные классы не могут быть созданы, что необязательно ограничивает будущие варианты. Например, позже мне может понадобиться состояние и методы, предоставляемые базовым классом, но не могут наследовать и не нуждаться в реализации интерфейса; если базовый класс является абстрактным, мне не повезло, но если базовый класс является обычным классом, то я могу создать экземпляр базового класса и удерживать его как компонент моего другого класса и делегировать экземпляр для повторного использования состояние/методы.

Да, это случается не часто, но дело в том, что абстракция базового класса предотвращает такое повторное использование/решение, когда нет оснований для этого.

Теперь, если экземпляр базового класса будет каким-то образом опасным, тогда сделайте его абстрактным - или, желательно, сделайте его менее опасным, если возможно; -)

Ответ 5

Подумайте, как банковский счет:

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

Затем вы можете создать два производных класса, называемых "SavingAccount" или "DebitAccount", которые могут иметь свое собственное конкретное поведение, в то же время используя поведение базового класса.

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

Если вы можете создать подобный сценарий для своих нужд, абстрактным способом является путь.

Ответ 6

Абстрактные классы предназначены для частично реализованных классов.

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

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

Ответ 7

Подумайте об этом по-другому.

Является ли мой базовый класс полным объектом на нем?

Если ответ отрицательный, сделайте его абстрактным. Если да, то вы, вероятно, захотите сделать его конкретным классом.

Ответ 8

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

Ответ 9

В зависимости от того, хотите ли вы, чтобы базовый класс был реализован самостоятельно или нет,

Как абстрактный класс, вы не можете создавать из него объекты.

Ответ 10

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

abstract class ADataAccess
{
    abstract public void Save();
}

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

public class DataAccess
{
    public void Save()
    {
        if ( _is_new )
        {
            Insert();
        }
        else if ( _is_modified )
        {
            Update();
        }
    }
}

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

interface ISaveable
{
    void Save();
    void Insert();
    void Update();
}

class UserAccount : ISavable
{
    void ISavable.Save() { ... }
    void ISavable.Insert() { ... }
    void ISavable.Update() { ... }
}

Еще одним вариантом может быть использование дженериков

class GenDataAccess<T>
{
    public void Save()
    {
        ...
    }
}

Все эти методы могут использоваться для определения определенного прототипа для классов, с которыми нужно работать. Способы убедиться, что код A может разговаривать с кодом B. И, конечно, вы можете смешивать и сопоставлять все вышеперечисленное по своему вкусу. Нет определенного правильного пути, но мне нравится определять интерфейсы и абстрактные классы, а затем ссылаться на интерфейсы. Таким образом, устранены некоторые мыслительные требования для "сантехники" в классах более высокого уровня, сохраняя при этом максимальную гибкость. (с интерфейсами отнимает требование использования абстрактного базового класса, но оставляет его в качестве опции).

Ответ 11

Я думаю, что многие из вас должны снова сменить базовые классы OO.

Основным основополагающим принципом в OOA/OOD является абстрактная абстрактная абстрактность, пока вы больше не сможете абстрагироваться. Если то, что вы смотрите на абстракцию, так и должно быть, вот что сказал вам ваш OOA/OOD. Однако, если вы сидите там, задаваясь вопросом, должен ли "код" быть абстрактным или нет, вы, очевидно, не знаете, что означает этот термин, и он должен снова изучить базовый OOA/OOD/OOP: -)

Более того, вы должны изучить шаблоны проектирования и гармоническую теорию, это очень поможет в ваших проектах OO!