抽象方法和虚拟方法有什么区别?在哪些情况下,建议使用抽象方法或虚拟方法?哪一种是最好的方法?
当前回答
我通过对以下课程(从其他答案)进行一些改进,使这一点更简单:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace TestOO
{
class Program
{
static void Main(string[] args)
{
BaseClass _base = new BaseClass();
Console.WriteLine("Calling virtual method directly");
_base.SayHello();
Console.WriteLine("Calling single method directly");
_base.SayGoodbye();
DerivedClass _derived = new DerivedClass();
Console.WriteLine("Calling new method from derived class");
_derived.SayHello();
Console.WriteLine("Calling overrided method from derived class");
_derived.SayGoodbye();
DerivedClass2 _derived2 = new DerivedClass2();
Console.WriteLine("Calling new method from derived2 class");
_derived2.SayHello();
Console.WriteLine("Calling overrided method from derived2 class");
_derived2.SayGoodbye();
Console.ReadLine();
}
}
public class BaseClass
{
public void SayHello()
{
Console.WriteLine("Hello\n");
}
public virtual void SayGoodbye()
{
Console.WriteLine("Goodbye\n");
}
public void HelloGoodbye()
{
this.SayHello();
this.SayGoodbye();
}
}
public abstract class AbstractClass
{
public void SayHello()
{
Console.WriteLine("Hello\n");
}
//public virtual void SayGoodbye()
//{
// Console.WriteLine("Goodbye\n");
//}
public abstract void SayGoodbye();
}
public class DerivedClass : BaseClass
{
public new void SayHello()
{
Console.WriteLine("Hi There");
}
public override void SayGoodbye()
{
Console.WriteLine("See you later");
}
}
public class DerivedClass2 : AbstractClass
{
public new void SayHello()
{
Console.WriteLine("Hi There");
}
// We should use the override keyword with abstract types
//public new void SayGoodbye()
//{
// Console.WriteLine("See you later2");
//}
public override void SayGoodbye()
{
Console.WriteLine("See you later");
}
}
}
其他回答
必须始终重写抽象函数。
因此:
抽象函数-当继承者必须提供自己的实现时虚拟-由继承人决定
解释:用类比。希望这对你有帮助。
上下文
我在一栋楼的21层工作。我对火很偏执。时不时地,在世界的某个地方,一场大火正在烧毁一座摩天大楼。但幸运的是,我们在这里有一本指导手册,说明发生火灾时该怎么做:
FireEscape()
不要收集物品步行至消防通道走出大楼
这基本上是一个名为FireEscape()的虚拟方法
虚拟方法
这个计划对99%的情况都很好。这是一个可行的基本计划。但有1%的可能性是消防通道被堵塞或损坏,在这种情况下,你会彻底完蛋,除非你采取一些激烈的行动,否则你会被烤焦。使用虚拟方法,您可以做到这一点:您可以使用自己版本的计划覆盖基本的FireEscape()计划:
运行到窗口跳出窗口降落伞安全到达底部
换句话说,虚拟方法提供了一个基本的计划,如果需要的话可以重写。如果程序员认为合适,子类可以重写父类的虚拟方法。
抽象方法
并非所有组织都训练有素。一些组织不进行消防演习。他们没有全面的逃跑政策。每个人都是为了自己。管理层只对现有的这种政策感兴趣。
换句话说,每个人都被迫开发自己的FireEscape()方法。一个人会走出消防通道。另一个人会跳伞。另一个人将使用火箭推进技术飞离大楼。另一个人会用绳索离开。管理层不在乎你如何逃跑,只要你有一个基本的FireEscape()计划——如果他们不这样做,你可以保证OHS会像一吨砖头一样砸在组织身上。这就是抽象方法的含义。
这两者又有什么区别?
抽象方法:子类被迫实现自己的FireEscape方法。使用虚拟方法,你有一个基本的计划等着你,但如果不够好,你可以选择实施自己的计划。
现在这并不难,是吗?
绑定是将名称映射到代码单元的过程。
后期绑定意味着我们使用名称,但延迟映射。换言之,我们首先创建/提及名称,然后让后续流程处理代码到该名称的映射。
现在考虑:
与人类相比,机器确实擅长搜索和排序与机器相比,人类确实擅长发明和创新
因此,简单的答案是:virtual是机器(运行时)的后期绑定指令,而abstract是人类(程序员)的后期约束指令
换句话说,虚拟意味着:
亲爱的运行时,通过执行您最擅长的操作将适当的代码绑定到此名称:搜索
抽象意味着:
亲爱的程序员,请尽你所能将适当的代码绑定到这个名字上:发明
为完整起见,重载意味着:
“亲爱的编译器,通过做你最擅长的事情,将适当的代码绑定到这个名称:排序”。
抽象函数没有实现,只能在抽象类上声明。这迫使派生类提供实现。
虚拟函数提供默认实现,它可以存在于抽象类或非抽象类上。
例如:
public abstract class myBase
{
//If you derive from this class you must implement this method. notice we have no method body here either
public abstract void YouMustImplement();
//If you derive from this class you can change the behavior but are not required to
public virtual void YouCanOverride()
{
}
}
public class MyBase
{
//This will not compile because you cannot have an abstract method in a non-abstract class
public abstract void YouMustImplement();
}
抽象方法没有实现。它在父类中声明。子类负责实现该方法。
虚拟方法应该在父类中有一个实现,它有助于子类选择是使用父类的该实现,还是为子类中的该方法自己有一个新的实现。
推荐文章
- 在支持循环和函数的语言中,是否存在“goto”的合法用例?
- 为什么不使用异常作为常规的控制流呢?
- 如何在方法中访问“静态”类变量?
- 什么是序列化?
- 为什么c#不提供c++风格的'friend'关键字?
- String, StringBuffer和StringBuilder
- 存储库和服务层的区别?
- 每个递归都可以转换成迭代吗?
- DDD -实体不能直接访问存储库的规则
- 为什么STL如此严重地基于模板而不是继承?
- 如何在Objective-C中声明类级属性?
- 面向方面编程与面向对象编程
- 什么是ORM,它是如何工作的,我应该如何使用它?
- 我能在服务器端应用程序(PHP、Ruby、Python等)上读取URL的哈希部分吗?
- c++中类似于java的instanceof