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

Не уверен, когда использовать абстрактное свойство, а когда нет

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

abstract class Human
{
  public GenderType Gender { get; set; }
  public string Name { get; set; }
  public Date Born { get; set; }
  public bool IsNerd { get; set; }

  abstract public void Speak();
  abstract public void Sleep();
  abstract public void AnoyingPeopleOnStackOverflow();
  //... so on
}

class Peter : Human
{
  //Peter is special, he got a second name
  //But thats all, everything else is the same as like on other humans
  public string SecondName { get; set; }

  //...override abstract stuff
}

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

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

4b9b3361

Ответ 1

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

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

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

Не помещайте свойство как abstract или virtual, если вы не хотите, чтобы оно было переопределено.

Используйте ключевое слово new, чтобы скрыть не абстрактный, не виртуальный элемент (это редко бывает хорошей идеей).

Как определить абстрактные свойства

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

См:

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

Ответ 2

Я знаю, что я хочу, чтобы они делали, мне все равно, как они это делают: интерфейс.

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

Я знаю, что я хочу, чтобы они делали, и как большинство из них это сделает: Конкретный класс с виртуальными членами.

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

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

Ответ 3

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

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

Если у вас, например, есть класс животных, его способность дышать не удастся отделить только от информации о том, что это животное, но это что-то очень важное:

public abstract class Animal {

  public abstract bool CanBreathe { get; }

}

Для рыбы и собаки реализация будет иной:

public class Dog : Animal {

   public override bool CanBreathe { get { return !IsUnderWater; } }

}

public class Fish : Animal {

   public override bool CanBreathe { get { return IsUnderWater; } }

}

Ответ 4

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

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

Пример правильного использования абстрактного свойства:

public class Car
{
    public abstract string Manufacturer { get; }
}

public class Odyssey : Car
{
    public override string Manufacturer
    {
         get 
         {
             return "Honda";
         }
    }
}

public class Camry : Car
{
    public override string Manufacturer
    {
         get 
         {
             return "Toyota";
         }
    }
}

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

Ответ 5

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

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

Ваша реализация сама по себе выглядит просто замечательно. Старался думать о разумном примере абстрактного свойства для Human, но не мог придумать ничего разумного.