xor*_*wer 76 c# oop virtual overriding new-operator
我是OOP的一些概念之间很困惑:virtual
,override
,new
和sealed override
.谁能解释这些差异?
我很清楚,如果要使用派生类方法,可以使用override
关键字,以便派生类覆盖基类方法.但我不确定new
,而且sealed override
.
Cha*_*thJ 101
该虚拟关键字用于修改的方法,属性,索引或事件声明,并允许它在派生类重写.例如,任何继承它的类都可以覆盖此方法:使用new修饰符显式隐藏从基类继承的成员.要隐藏继承的成员,请使用相同的名称在派生类中声明它,并使用new修饰符对其进行修改.
这与多态性有关.在引用上调用虚方法时,引用引用的对象的实际类型用于决定使用哪种方法实现.当在派生类中重写基类的方法时,即使调用代码没有"知道"该对象是派生类的实例,也会使用派生类中的版本.例如:
public class Base
{
public virtual void SomeMethod()
{
}
}
public class Derived : Base
{
public override void SomeMethod()
{
}
}
...
Base d = new Derived();
d.SomeMethod();
Run Code Online (Sandbox Code Playgroud)
如果重写Base.SomeMethod,将最终调用Derived.SomeMethod.
现在,如果使用new关键字而不是override,派生类中的方法不会覆盖基类中的方法,它只是隐藏它.在这种情况下,代码如下:
public class Base
{
public virtual void SomeOtherMethod()
{
}
}
public class Derived : Base
{
public new void SomeOtherMethod()
{
}
}
...
Base b = new Derived();
Derived d = new Derived();
b.SomeOtherMethod();
d.SomeOtherMethod();
Run Code Online (Sandbox Code Playgroud)
首先调用Base.SomeOtherMethod,然后调用Derived.SomeOtherMethod.它们实际上是两个完全独立的方法,它们碰巧具有相同的名称,而不是覆盖基本方法的派生方法.
如果未指定new或覆盖,则结果输出与指定new相同,但您也会收到编译器警告(因为您可能不知道您在基类中隐藏了一个方法方法,或者你可能想要覆盖它,只是忘了包含关键字).
覆盖的属性声明可能包括sealed修饰符.使用此修饰符可防止派生类进一步覆盖该属性.密封财产的存取也是密封的.
Lok*_*sus 35
任何方法都可以覆盖(= virtual
)或不覆盖.决定是由定义方法的人做出的:
class Person
{
// this one is not overridable (not virtual)
public String GetPersonType()
{
return "person";
}
// this one is overridable (virtual)
public virtual String GetName()
{
return "generic name";
}
}
Run Code Online (Sandbox Code Playgroud)
现在,您可以覆盖那些可覆盖的方法:
class Friend : Person
{
public Friend() : this("generic name") { }
public Friend(String name)
{
this._name = name;
}
// override Person.GetName:
public override String GetName()
{
return _name;
}
}
Run Code Online (Sandbox Code Playgroud)
但是你不能覆盖该GetPersonType
方法,因为它不是虚拟的.
让我们创建这些类的两个实例:
Person person = new Person();
Friend friend = new Friend("Onotole");
Run Code Online (Sandbox Code Playgroud)
当实例GetPersonType
调用非虚方法时,Fiend
它实际上Person.GetPersonType
被调用:
Console.WriteLine(friend.GetPersonType()); // "person"
Run Code Online (Sandbox Code Playgroud)
当虚拟方法GetName
被Friend
实例调用时,它Friend.GetName
被调用:
Console.WriteLine(friend.GetName()); // "Onotole"
Run Code Online (Sandbox Code Playgroud)
当虚拟方法GetName
被Person
实例调用时,它Person.GetName
被调用:
Console.WriteLine(person.GetName()); // "generic name"
Run Code Online (Sandbox Code Playgroud)
当调用非虚方法时,不会查找方法体 - 编译器已经知道需要调用的实际方法.而使用虚方法,编译器无法确定调用哪一个,并且在类层次结构中的运行时从上到下friend.GetName
查找,从调用该方法的实例类型开始:因为它看起来从Friend
类开始立即找到它,因为person.GetName
它从Person
那里开始并在那里找到它.
有时你创建一个子类,覆盖一个虚方法,你不希望在层次结构中有任何更多的覆盖 - 你用sealed override
它(说你是最后一个覆盖方法):
class Mike : Friend
{
public sealed override String GetName()
{
return "Mike";
}
}
Run Code Online (Sandbox Code Playgroud)
但有时你的朋友迈克决定改变他的性别,因此他的名字改为爱丽丝:)你可以改变原始代码或改为亚迈克:
class Alice : Mike
{
public new String GetName()
{
return "Alice";
}
}
Run Code Online (Sandbox Code Playgroud)
在这里,您可以使用相同的名称创建一个完全不同的方法(现在您有两个).调用哪种方法和时间?这取决于你如何称呼它:
Alice alice = new Alice();
Console.WriteLine(alice.GetName()); // the new method is called, printing "Alice"
Console.WriteLine(((Mike)alice).GetName()); // the method hidden by new is called, printing "Mike"
Run Code Online (Sandbox Code Playgroud)
当您从调用它Alice
的角度你打电话Alice.GetName
,当从Mike
的-你打电话Mike.GetName
.这里没有进行运行时查找 - 因为两种方法都是非虚拟的.
您始终可以创建new
方法 - 您隐藏的方法是否为虚拟方法.
这也适用于属性和事件 - 它们表示为下面的方法.
ja7*_*a72 17
默认情况下,除非声明了方法virtual
,否则不能在派生类中重写方法,或者abstract
.virtual
表示在调用之前检查更新的实现并且abstract
意味着相同,但保证在所有派生类中重写.此外,基类中不需要实现,因为它将在其他地方重新定义.
上面的例外是new
修饰符.未声明virtual
或abstract
可以使用new
派生类中的修饰符重新定义的方法.当在基类中调用该方法时,执行基本方法,并且在派生类中调用时,执行新方法.所有new
关键字允许您在类层次结构中使用两个具有相同名称的方法.
最后,sealed
修饰符会破坏virtual
方法链并使它们不再可覆盖.这不经常使用,但选项就在那里.通过从前一个类派生的3个类的链来更有意义
A -> B -> C
Run Code Online (Sandbox Code Playgroud)
如果A
有一个virtual
或abstract
方法,即overridden
在B
,那么它也可以防止C
从通过声明它再次改变它sealed
在B
.
sealed
也用于classes
,这是您通常会遇到此关键字的地方.
我希望这有帮助.
public class Base
{
public virtual void SomeMethod()
{
Console.WriteLine("B");
}
}
public class Derived : Base
{
//Same method is written 3 times with different keywords to explain different behaviors.
//This one is Simple method
public void SomeMethod()
{
Console.WriteLine("D");
}
//This method has 'new' keyword
public new void SomeMethod()
{
Console.WriteLine("D");
}
//This method has 'override' keyword
public override void SomeMethod()
{
Console.WriteLine("D");
}
}
Run Code Online (Sandbox Code Playgroud)
现在第一件事
Base b=new Base();
Derived d=new Derived();
b.SomeMethod(); //will always write B
d.SomeMethod(); //will always write D
Run Code Online (Sandbox Code Playgroud)
现在关键词都是关于多态性的
Base b = new Derived();
Run Code Online (Sandbox Code Playgroud)
virtual
的基类和覆盖Derived
会给d(多态性).override
without virtual
in Base
会出错.virtual
将写'B'并带有警告(因为没有完成多态).new
那个简单方法之前写的警告Derived
.new
关键字是另一个故事,它只是隐藏警告,告诉基类中有相同名称的属性.virtual
或者new
两者都是相同的,除了
新修饰符
new
并且override
不能在相同的方法或属性之前使用.
sealed
在任何类或方法锁定它以在Derived类中使用之前它会产生编译时错误. 归档时间: |
|
查看次数: |
91680 次 |
最近记录: |