Когда следует объявлять член класса виртуальным (C #) / переопределяемым (VB.NET)?

Почему бы мне не выбрать абстрактное? Каковы ограничения на объявление виртуального члена класса? Можно ли объявить виртуальными только методы?


person Alex Angas    schedule 17.09.2008    source источник


Ответы (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");
        }
    }
}
person Kokuma    schedule 17.09.2008

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

Да, виртуальными могут быть только методы.

person Phil Wright    schedule 17.09.2008

Член должен быть объявлен виртуальным, если существует базовая реализация, но существует вероятность того, что эта функциональность будет переопределена в дочернем классе. Virtual также может использоваться вместо абстрактного, чтобы реализация метода была необязательной (т. Е. Базовая реализация является пустым методом)

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

И методы, и свойства можно пометить как виртуальные.

person Richard Szalay    schedule 17.09.2008

Здесь есть одна хитрость, о которой следует помнить о Windows Forms.

Если вам нужен Control / UserControl, от которого вы можете наследовать, даже если у вас нет логики в базовом классе, вы не хотите, чтобы он был абстрактным, потому что в противном случае вы не сможете использовать конструктор в производных классах: http://www.urbanpotato.net/default.aspx/document/2001

person Benjol    schedule 17.09.2008

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

Да, виртуальными можно объявлять только методы.

person Maximilian    schedule 17.09.2008

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

Я не уверен, что вы имеете в виду под «ограничениями», поэтому не могу ответить на этот вопрос.

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

person Seb Rose    schedule 17.09.2008

Ваш вопрос больше связан со стилем, чем с техническими деталями. Я думаю, что эта книга https://rads.stackoverflow.com/amzn/click/com/0321246756 есть отличное обсуждение вашего и многих других вопросов.

person Hallgrim    schedule 17.09.2008

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

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

С другой стороны, если вы реализуете класс Dog, вы можете реализовать метод Bark () в этом случае, вы можете реализовать звук лая по умолчанию и поместите его в класс Dog, тогда как некоторые унаследованные классы, такие как класс Chiwawa, могут захотеть переопределить этот метод и реализовать определенный звук лая. В этом случае метод bark будет реализован как виртуальный, и вы сможете создавать экземпляры Dogs, а также Chiwawas.

person Sakin    schedule 17.09.2008

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

person Chris Canal    schedule 18.09.2008