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

Почему С# допускает абстрактный класс без абстрактных элементов?

Спецификация С#, раздел 10.1.1.1, указывает:

Разрешен абстрактный класс (но не требуется) содержать абстрактные члены.

Это позволяет мне создавать классы следующим образом:

public abstract class A
{
    public void Main() 
    {
        // it full of logic!
    }
}

Или даже лучше:

public abstract class A
{
    public virtual void Main() { }
}

public abstract class B : A
{
    public override sealed void Main()
    {
        // it full of logic!
    }
}

Это действительно конкретный класс; он только абстрактный, поскольку его невозможно создать. Например, если бы я хотел выполнить логику в B.Main(), мне пришлось бы сначала получить экземпляр B, что невозможно.

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

Иными словами, почему С# разрешает абстрактный класс только с конкретными членами?

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

4b9b3361

Ответ 1

Возможно, хорошим примером является общий базовый класс, который предоставляет общие свойства и, возможно, другие члены для производных классов, но не представляет собой конкретный объект. Например:

public abstract class Pet
{
    public string Name{get;set;}
}

public class Dog : Pet
{
    public void Bark(){ ... }
}

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

Различие заключается в том, что вместо предоставления метода, который должен быть переопределен разработчиками, базовый класс объявляет, что все домашние животные состоят как минимум из свойства Name.

Ответ 2

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

Например:

public abstract class FourLeggedAnimal
{

    public void Walk()
    {
        // most 4 legged animals walk the same (silly example, but it works)
    }

    public void Chew()
    {

    }
}

public class Dog : FourLeggedAnimal
{
    public void Bark()
    {
    }
}

public class Cat : FourLeggedAnimal
{
    public void Purr()
    {
    }
}

Ответ 3

Я думаю, что несколько более точное представление вашего вопроса будет: Почему С# разрешает абстрактный класс только с конкретными членами?

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

Ответ 4

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

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

Этот выбор дизайна может иметь отношение к созданию объектов, которые (рискуют смешать терминологию) абстракциями объектов реального мира и с удобочитаемостью. Вы можете объявить параметры типа Car, но не хотите, чтобы объекты были декларируемыми как Car - вы хотите, чтобы каждый объект типа Car был создан как Truck, Sedan, Coupe или Roadster. Тот факт, что Car не требует, чтобы наследователи добавляли реализацию, не умаляет его значения как абстрактную версию своих наследников, которые сами не могут быть созданы.

Ответ 5

Абстрактный означает предоставление абстракции поведения. Например, автомобиль является абстрактной формой. В нем нет реального экземпляра реального мира, но мы можем сказать, что автомобиль имеет ускоряющее поведение. В частности, Ford Ikon является транспортным средством, а Yamaha FZ является транспортным средством. Оба они ускоряют поведение.

Если вы сейчас сделаете это в форме класса. Автомобиль - это абстрактный класс с методом ускорения. Хотя вы можете и не можете предоставить какой-либо абстрактный метод. Но деловая необходимость заключается в том, что транспортное средство не должно создаваться. Следовательно, вы делаете его абстрактным. Остальные два класса - Ikon и FZ - это конкретные классы, относящиеся к классу Vehicle. Эти два будут иметь свои собственные свойства и поведение.

Ответ 6

Что касается использования, использование abstract в объявлении класса, но без абстрактных элементов совпадает с классом public, но с использованием protected в его конструкторах. Оба заставляют класс быть выведенным для того, чтобы он был создан.

Однако, что касается самодокументирующего кода, помечая класс abstract, он сообщает другим, что этот класс никогда не должен создаваться сам по себе, даже если он не имеет элементов virtual или abstract, В то время как защита конструкторов не делает такого утверждения.

Ответ 7

Компилятор не предотвращает реализацию логики реализации, но в вашем случае я бы просто опустил abstract?! BTW некоторые методы могут быть реализованы с помощью { throw Exception("must inherit"); }, и компилятор не смог отличить полностью реализованные классы и функции, включая только throw.

Ответ 8

Вот потенциальная причина:

Супертип слоя

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

- Мартин Фаулер

Нет причин не допускать только конкретные методы в абстрактном классе - это просто менее распространено. Layer Supertype - это случай, когда это может иметь смысл.

Ответ 9

Я вижу абстрактные классы, служащие двум основным целям:

  • Неполный класс, который должен быть специализированным, чтобы предоставить конкретную услугу. Здесь абстрактные члены будут необязательными. Класс предоставит некоторые службы, которые могут использовать дочерние классы, и может определять абстрактные члены, которые он использует для предоставления своей службы, например, в Шаблон метода шаблона. Этот тип абстрактного класса предназначен для создания иерархии наследования .

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