在MSDN中,提到在C#中虚方法,问题
http://msdn.microsoft.com/en-us/library/9fkccyh4(VS.80).aspx
我对包括财产申报困惑是什么项目意味着“虚拟继承属性可以在派生类中重写使用覆盖修饰符。“?
(这是虚拟和抽象间的第二差异)提前
感谢, 乔治
在MSDN中,提到在C#中虚方法,问题
http://msdn.microsoft.com/en-us/library/9fkccyh4(VS.80).aspx
我对包括财产申报困惑是什么项目意味着“虚拟继承属性可以在派生类中重写使用覆盖修饰符。“?
(这是虚拟和抽象间的第二差异)提前
感谢, 乔治
你能解释一下而已混乱?属性可以像任何其他方法一样被覆盖。
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 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; }
}
在您从抽象类派生类(上面的抽象类是只为说明目的,因为它没有任何方法/性的判定有一个实现,你可以创建一个接口,而不是一个抽象类),你将不得不提供MyProperty
的实施。否则,它不会编译。 通过'覆盖'MyProperty来做到这一点,你不想引入一个新成员,而只是提供一个以前定义的属性的实现。
public class ConcreteClass : AbstractClass
{
public override MyProperty {
get
{
return _someValue;
}
set
{
if(_someValue != value) _someValue = value;
}
}
好吧,假设您有一个基类,并且该基类本身是从另一个类派生的。
public class Bar : Foo
{
virtual public int SomeProperty { get; set; }
}
什么virtual关键字意味着,在从酒吧派生的类,则可以覆盖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;
}
}
}
澄清:当使用类型巴兹的对象,它的版本SomeProperty被调用,除非类型被转换为Bar。如果你将Baz的SomeProperty定义为虚拟的,那么从Baz派生出来的类也可以覆盖它(事实上,这可能是必需的 - 不能从脑海中回想起来)。
进一步说明:抽象方法没有实现;当你添加一个到您的类,还必须将类标记为抽象的,你不能实例化它的新的实例,就像这样:
MyAbstractType m = new MyAbstractType();
虚拟成员,而另一方面,可以有一个实现(如SomeProperty,上面),所以你不必标记类的抽象,你可以实例化它们。
我可以理解混乱。我曾去过那里,所以我将分享我如何保持基本差异直...
virtual
与abstract
:
如果一个类的方法(或属性)是 标virtual
,那么可能是 使用override
关键字覆盖,如果你选择继承 (又名获得)从该类。 virtual
关键字旨在唤起这样的想法:该方法可能是也可能不是实际调用的方法。因此,我始终认为virtual
成员为默认实现,这意味着它代表了可以推广的功能,例如类中的Eat()
方法,这可能涉及用手进食。但是,ChineseHuman
类可能会替代默认实现的Eat()
,以便允许替代使用斩波棒的实现。最后,由于虚拟方法和属性是默认实现,定义该成员的类必须提供方法或属性的完整实现。所有Human
对象必须知道如何Eat()
。
面向对象的思维方式可能会声明virtual
成员代表本能。 Eat()
是Human
类对象的本能。 A ChineseHuman
可能学习到Eat()
用筷子。
如果一个类的方法(或属性)是 标记abstract
,那么它必须是 使用的override
关键字,如果你选择从该类继承 覆盖。 abstract
关键字旨在唤起类只有支持该成员表示的功能,并且没有任何可以通用于该功能的通用逻辑。换句话说,abstract
成员只有概念,因此他们缺乏一个实现。当我们实现一个继承关系时,C#向我们询问override
抽象成员有点令人困惑,但在这种情况下,这实际上意味着我们用一个具体实现覆盖了空的概念。Human
类的abstract
成员的示例可能是Speak()
。所有的对象都不会有一种常见的说话方式,也不是本能的,因为它需要语言来表达。注意:有些人可能会认为Speak()
属于interface
。
面向对象的思维方式可能会声明abstract
成员表示要学习的行为(方法)以及要获得的知识或信念(属性)。到Speak()
是学过行为的一个Human
类对象。 A ChineseHuman
可能会学习到Speak()
与EnglishHuman
不同,并且都不知道如何Speak()
,因为它们都是Human
。
细微差别:
virtual
方法并不需要重写。virtual
类。abstract
成员只能出现在abstract
类。在上面的例子中,在Human
类别上使用abstract
方法意味着Human
是abstract
类别,并且因此不能使用短语var baby = new Human();
实例化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
关键字(请参阅下面的“C#中的方法隐藏”参考)隐藏BabyHuman
的BabyHuman
实现Speak()
及其自己的实现。abstract
类可以有virtual
成员。这是interface
和abstract
类之间的主要区别。从这个意义上讲,一个abstract
类可以定义类的行为的合同和模板,而interface
只定义合同。代码参考:在C#
我的困惑不是重写属性,而是为什么它是抽象和虚拟之间的差异 - “”通过包含使用override修饰符的属性声明,可以在派生类中重写虚拟继承属性。“?请参阅我引用的MSDN上下文。 – George2 2009-03-03 13:13:45
抽象成员没有实现,所以_必须被覆盖。虚拟成员有一个实现,并且可以覆盖_may_。这是不同的。 – 2009-03-03 13:18:42
明白了,MSDN的话太模糊了。 :-) – George2 2009-03-03 13:21:03