Почему бы мне не выбрать абстрактное? Каковы ограничения на объявление виртуального члена класса? Можно ли объявить виртуальными только методы?
Когда следует объявлять член класса виртуальным (C #) / переопределяемым (VB.NET)?
Ответы (9)
Абстрактный метод или свойство (оба могут быть виртуальными или абстрактными) могут быть объявлены только в абстрактном классе и не могут иметь тела, т.е. вы не можете реализовать его в своем абстрактном классе.
У виртуального метода или свойства должно быть тело, т.е. вы должны предоставить реализацию (даже если тело пусто).
Если кто-то захочет использовать ваш абстрактный класс, он должен будет реализовать класс, который наследуется от него, и явно реализовать абстрактные методы и свойства, но может не переопределять виртуальные методы и свойства.
Пример:
using System;
using C=System.Console;
namespace Foo
{
public class Bar
{
public static void Main(string[] args)
{
myImplementationOfTest miot = new myImplementationOfTest();
miot.myVirtualMethod();
miot.myOtherVirtualMethod();
miot.myProperty = 42;
miot.myAbstractMethod();
}
}
public abstract class test
{
public abstract int myProperty
{
get;
set;
}
public abstract void myAbstractMethod();
public virtual void myVirtualMethod()
{
C.WriteLine("foo");
}
public virtual void myOtherVirtualMethod()
{
}
}
public class myImplementationOfTest : test
{
private int _foo;
public override int myProperty
{
get { return _foo; }
set { _foo = value; }
}
public override void myAbstractMethod()
{
C.WriteLine(myProperty);
}
public override void myOtherVirtualMethod()
{
C.WriteLine("bar");
}
}
}
Вы должны использовать abstract, если не хотите определять какую-либо реализацию в базовом классе и хотите принудительно определить ее в любых производных классах. Определите его как виртуальный, если вы хотите предоставить реализацию по умолчанию, которая может быть отменена производными классами.
Да, виртуальными могут быть только методы.
Член должен быть объявлен виртуальным, если существует базовая реализация, но существует вероятность того, что эта функциональность будет переопределена в дочернем классе. Virtual также может использоваться вместо абстрактного, чтобы реализация метода была необязательной (т. Е. Базовая реализация является пустым методом)
Нет ограничений при настройке члена как виртуального, но виртуальные члены работают медленнее, чем невиртуальные методы.
И методы, и свойства можно пометить как виртуальные.
Здесь есть одна хитрость, о которой следует помнить о Windows Forms.
Если вам нужен Control / UserControl, от которого вы можете наследовать, даже если у вас нет логики в базовом классе, вы не хотите, чтобы он был абстрактным, потому что в противном случае вы не сможете использовать конструктор в производных классах: http://www.urbanpotato.net/default.aspx/document/2001
Если вы хотите реализовать его в своем базовом классе, вы делаете его виртуальным, если нет - абстрактным.
Да, виртуальными можно объявлять только методы.
Абстракция означает, что вы не можете предоставить реализацию по умолчанию. Это, в свою очередь, означает, что все подклассы должны предоставлять реализацию абстрактного метода, чтобы быть инстанцируемыми (конкретными).
Я не уверен, что вы имеете в виду под «ограничениями», поэтому не могу ответить на этот вопрос.
Свойства можно объявлять виртуальными, но вы также можете концептуально рассматривать их как методы.
Ваш вопрос больше связан со стилем, чем с техническими деталями. Я думаю, что эта книга https://rads.stackoverflow.com/amzn/click/com/0321246756 есть отличное обсуждение вашего и многих других вопросов.
Прежде всего, отвечу на второй вопрос. Виртуальными можно объявлять только методы. Вы бы выбрали виртуальный вместо абстрактного, если вам нужны некоторые функции по умолчанию в вашем базовом классе, но вы хотите оставить возможность переопределения этой функции классами, которые наследуются от вашего базового класса. Например:
Если вы реализуете класс Shape, у вас, вероятно, будет метод под названием getArea (), который возвращает площадь вашей формы. В этом случае для метода getArea () в классе Shape нет поведения по умолчанию, поэтому вы должны реализовать его как абстрактный. Реализация метода как абстрактного не позволит вам создать экземпляр объекта Shape.
С другой стороны, если вы реализуете класс Dog, вы можете реализовать метод Bark () в этом случае, вы можете реализовать звук лая по умолчанию и поместите его в класс Dog, тогда как некоторые унаследованные классы, такие как класс Chiwawa, могут захотеть переопределить этот метод и реализовать определенный звук лая. В этом случае метод bark будет реализован как виртуальный, и вы сможете создавать экземпляры Dogs, а также Chiwawas.
Я лично отмечу большинство методов и свойств виртуальными. Я много использую прокси и ленивую загрузку, поэтому мне не нужно беспокоиться об изменении чего-либо в будущем.