抽象方法和虚拟方法有什么区别?在哪些情况下,建议使用抽象方法或虚拟方法?哪一种是最好的方法?
当前回答
抽象方法是一种必须实现才能生成具体类的方法。声明在抽象类中(任何具有抽象方法的类都必须是抽象类),并且必须在具体类中实现。
虚拟方法是一种可以在派生类中使用重写重写的方法,替换超类中的行为。如果不覆盖,则获得原始行为。如果你这样做,你总会得到新的行为。这与不能重写但可以隐藏原始方法的非虚拟方法相反。这是使用新修改器完成的。
请参见以下示例:
public class BaseClass
{
public void SayHello()
{
Console.WriteLine("Hello");
}
public virtual void SayGoodbye()
{
Console.WriteLine("Goodbye");
}
public void HelloGoodbye()
{
this.SayHello();
this.SayGoodbye();
}
}
public class DerivedClass : BaseClass
{
public new void SayHello()
{
Console.WriteLine("Hi There");
}
public override void SayGoodbye()
{
Console.WriteLine("See you later");
}
}
当我实例化DerivedClass并调用SayHello或SayGoodbye时,我会得到“Hi There”和“See you later”。如果我打电话给HelloGoodbye,我会收到“你好”和“再见”。这是因为SayGoodbye是虚拟的,可以被派生类替换。SayHello只是隐藏的,所以当我从基类调用它时,我会得到原始方法。
抽象方法是隐式虚拟的。它们定义了必须存在的行为,更像是一个接口。
其他回答
抽象方法:当类包含抽象方法时,该类必须声明为抽象的。抽象方法没有实现,因此派生自该抽象类的类必须为该抽象方法提供实现。
虚拟方法:类可以具有虚拟方法。虚拟方法有一个实现。当从具有虚拟方法的类继承时,可以重写虚拟方法并提供额外的逻辑,或者用自己的实现替换逻辑。
何时使用什么:在某些情况下,您知道某些类型应该有一个特定的方法,但您不知道该方法应该有什么实现。在这种情况下,您可以创建包含具有此签名的方法的接口。然而,如果您有这样的情况,但您知道该接口的实现者也将有另一个通用方法(您已经可以为其提供实现),那么您可以创建一个抽象类。然后,这个抽象类包含抽象方法(必须重写)和另一个包含“公共”逻辑的方法。
如果您有一个可以直接使用的类,但您希望继承者能够更改某些行为,则应使用虚拟方法,尽管这不是强制性的。
上面的大多数示例都使用代码,而且非常好。我不需要补充他们所说的内容,但以下是一个简单的解释,使用了类比而不是代码/技术术语。
简单解释-使用类比进行解释
抽象方法
想想乔治·W·布什。他对士兵们说:“去伊拉克打仗吧”。就这样,他所说的就是必须战斗。他没有具体说明这将如何发生。但我的意思是,你不能只是出去“战斗”:那到底意味着什么?我是用B-52还是我的人字架?这些具体细节留给其他人。这是一种抽象方法。
虚拟方法
大卫·彼得雷乌斯在军队中地位很高。他定义了战斗的含义:
找到敌人中和他。之后喝杯啤酒
问题是这是一种非常通用的方法。这是一个有效的好方法,但有时不够具体。对彼得雷乌斯来说,好事是他的命令有回旋余地和范围——他允许其他人根据他们的特殊要求改变他对“战斗”的定义。
私人职业博客阅读彼得雷乌斯的命令,并根据他的特殊要求获得了实施自己版本的战斗的许可:
找到敌人。朝他的头部开枪。回家吧喝啤酒。
努里·马利基也收到彼得雷乌斯的同样命令。他也要战斗。但他是一名政治家,而不是一名步兵。显然,他不能四处射击他的政治敌人的头部。因为彼得雷乌斯给了他一种虚拟的方法,所以马利基可以根据自己的具体情况,实施自己的战斗方法:
找到敌人。让他以一些捏造的罪名被捕。回家吧喝啤酒。
换言之,虚拟方法提供了样板指令——但这些是一般指令,可以由军队继承人根据他们的具体情况做出更具体的说明。
两者之间的区别
乔治·布什没有证明任何实施细节。这必须由其他人提供。这是一种抽象方法。另一方面,彼得雷乌斯确实提供了实施细节,但他已经允许他的下属,如果他们能想出更好的办法,可以用自己的版本推翻他的命令。
希望这会有所帮助。
抽象函数(方法):
● 抽象方法是用关键字abstract声明的方法。
● 它没有身体。
● 它应该由派生类实现。
● 如果方法是抽象的,那么类应该是抽象的。
虚拟函数(方法):
● 虚方法是用关键字virtual声明的方法,它可以通过使用override关键字由派生类方法重写。
● 是否重写它取决于派生类。
必须始终重写抽象函数。
因此:
抽象函数-当继承者必须提供自己的实现时虚拟-由继承人决定
抽象方法没有实现。它在父类中声明。子类负责实现该方法。
虚拟方法应该在父类中有一个实现,它有助于子类选择是使用父类的该实现,还是为子类中的该方法自己有一个新的实现。
推荐文章
- 在支持循环和函数的语言中,是否存在“goto”的合法用例?
- 为什么不使用异常作为常规的控制流呢?
- 如何在方法中访问“静态”类变量?
- 什么是序列化?
- 为什么c#不提供c++风格的'friend'关键字?
- String, StringBuffer和StringBuilder
- 存储库和服务层的区别?
- 每个递归都可以转换成迭代吗?
- DDD -实体不能直接访问存储库的规则
- 为什么STL如此严重地基于模板而不是继承?
- 如何在Objective-C中声明类级属性?
- 面向方面编程与面向对象编程
- 什么是ORM,它是如何工作的,我应该如何使用它?
- 我能在服务器端应用程序(PHP、Ruby、Python等)上读取URL的哈希部分吗?
- c++中类似于java的instanceof