[英]issue of virtual method in C#
在MSDN中,提到了
http://msdn.microsoft.com/zh-CN/library/9fkccyh4(VS.80).aspx
我感到困惑的是,“通过包含使用override修饰符的属性声明,可以在派生类中覆盖虚拟继承的属性”是什么意思?
(这是虚拟和抽象之间的第二个区别)
预先感谢乔治
虚拟和抽象之间的唯一区别是,抽象方法或属性在定义它的类(抽象类)中没有实现,并且必须在子类中重写它; 而虚拟方法或属性在定义它的类中具有实现,因此在子类中重写它不是强制性的。
public abstract AbstractClass
{
// This class cannot be instantiated, since it is
// abstract, and the class is abstract because
// it has an abstract member
public abstract MyProperty {get; set; }
}
在您从AbstractClass派生的类中(上面的AbstractClass仅用于说明目的;由于它没有实现的方法/属性,因此您可以创建接口而不是抽象类),您将必须提供以下实现MyProperty
。 否则,它将无法编译。 您可以通过“覆盖” MyProperty来执行此操作,您不想引入新成员,而只是为先前定义的属性提供实现。
public class ConcreteClass : AbstractClass
{
public override MyProperty {
get
{
return _someValue;
}
set
{
if( _someValue != value ) _someValue = value;
}
}
我能理解混乱。 我以前去过那里,所以我将分享如何保持基本的差异...
virtual
与abstract
:
如果将一个类方法(或属性)标记为virtual
,那么如果您选择从该类继承 (又称为derive ),则可以使用override
关键字将其override
。
virtual
关键字旨在引起这种想法,即该方法可能是实际调用的方法,也可能不是。 因此,我始终将virtual
成员视为默认实现 ,这意味着它表示可以泛化的功能,例如Human
类上的Eat()
方法,可能涉及用手吃饭。 但是, ChineseHuman
类可能会覆盖Eat()
的默认实现 ,以便允许使用筷子的实现。 最后,由于虚拟方法和属性是默认实现 ,因此定义该成员的类必须提供方法或属性的完整实现。 所有Human
对象必须知道如何 Eat()
。
面向对象的思维方式可以声明virtual
成员代表本能 。 Eat()
是Human
类对象的本能 。 ChineseHuman
可能会用筷子学习 Eat()
。
如果将类方法(或属性)标记为abstract
,则如果您选择从该类继承 ,则必须使用override
关键字将其override
。
abstract
关键字旨在引起这样的想法:该类仅支持成员表示的功能,并且没有可以针对该功能归纳的任何通用逻辑。 换句话说, abstract
成员只是概念上的 ,因此缺少实现。 在实现继承关系时,C#要求我们override
抽象成员有点令人困惑,但是在这种情况下,这实际上意味着我们正在通过具体的实现重写空概念。 Human
类的abstract
成员的一个示例可能是Speak()
。 对于所有Human
对象来说,不会有一种通用的说话方式,也不是本能的,因为它需要语言来表达。 注意:有人可能会说Speak()
属于interface
。
面向对象的思维方式可以声明abstract
成员表示要学习的行为(方法)和要获取的知识或信念(属性)。 Speak()
是Human
类对象的学习行为。 一个ChineseHuman
可以学会Speak()
不同于一个EnglishHuman
也不知道怎么Speak()
仅仅是因为他们都是Human
。
细微差别:
virtual
方法不需要被覆盖。 virtual
类这样的东西。 abstract
成员只能出现在abstract
类上。 在上述例子中,具有abstract
的方法Human
类意味着Human
是一个abstract
类,而且,因此,一个Human
不能使用短语实例化var baby = new Human();
。 相反, BabyHuman
类应该继承自Human
,并且应实例化为var baby = new BabyHuman();
。 因为BabyHuman()
是Human
和EnglishHuman
和ChineseHuman
都还继承Human
, EnglishHuman
可以继承BabyHuman
,而不是Human
。 成为Human
是abstract
因为我们不仅仅是单纯的Human
。 abstract
成员不能被隐藏,只有它们的override
实现可以(在继承链的更进一步)。 例如, BabyHuman
必须实现abstract
Speak()
方法作为override
。 如果EnglishHuman
继承自BabyHuman
,则可以使用new
关键字使用自己的实现隐藏Speak()
的BabyHuman
实现(请参见下面的“ C#中的方法隐藏”)。 abstract
类可以具有virtual
成员。 这是interface
和abstract
类之间的主要区别。 从这个意义上讲, abstract
类既可以定义合同,也可以定义该类行为的模板,而interface
只能定义合同。 代码参考:
您能解释一下令人困惑的地方吗? 可以像其他任何方法一样覆盖属性。
public class Base {
public virtual int Prop1 { get { ... } set { ... } }
}
public class Derived : Base {
public override int Prop1 { get { ... } set { ... } }
如果在基类中声明虚拟方法,则可以在派生类中重写该方法。
例
class MyBaseClass
{
public virtual void MyOverridableMethod()
{
...
}
}
class MyDerivedClass : MyBaseClass
{
public override void MyOverridableMethod()
{
...
}
}
注意MyDerivedClass中的override修饰符。
好的,假设您有一个基类,并且该基类本身是从另一个类派生的。
public class Bar : Foo
{
virtual public int SomeProperty { get; set; }
}
virtual关键字的意思是,在从Bar派生的类中,您可以重写SomeProperty来更改其行为:
public class Baz : Bar
{
private int thisInt;
override public int SomeProperty
{
get { return thisInt; }
set
{
if(value < 0)
{
throw new ArgumentException("Value must be greater than or equal to zero.");
}
thisInt = 0;
}
}
}
说明:使用Baz类型的对象时,将调用其SomeProperty版本,除非将该类型强制转换为Bar。 如果您将Baz的SomeProperty定义为虚拟的,则从Baz派生的类也可以覆盖它(实际上,这可能是必需的-无法立即记住)。
进一步说明:抽象方法没有实现; 当您将一个类添加到您的类时,您还必须将该类标记为抽象类,并且无法实例化该类的新实例,如下所示:
MyAbstractType m = new MyAbstractType();
另一方面,虚拟成员可以有一个实现(例如上面的SomeProperty),因此您不必标记类的抽象,就可以实例化它们。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.