c#中抽象类和虚方法的区别?

本文深入浅出地讲解了抽象类与虚方法的概念及其在编程中的应用。通过实例介绍了抽象类如何描述事物共性,以及虚方法如何允许子类进行重写以实现功能的定制。

你说的是抽象类和虚方法吧!

其实这是哲学的思维方式,所谓哲学就是建立事实基础上,是人类对世界的思考和认识。

要理解抽象类就必须要有一定的编程经验,就好像要理解哲学就需要有一定的生活经验。跟一个没有大量编程经验的人将设计模式那也是扯蛋!

所以作为一个新手,特别是没有面向对象编程经验的来说,不理解抽象类是很正常的,等你有了一定的编程经验,你自然而然就会理解了。

先看看MSDN的关于抽象类和虚方法的解释:
使用 abstract 关键字可以创建仅用于继承用途的类和类成员,即定义派生的非抽象类的功能。
abstract 修饰符可以和类、方法、属性、索引器及事件一起使用。在类声明中使用 abstract 修饰符以指示某个类只能是其他类的基类。标记为抽象或包含在抽象类中的成员必须通过从抽象类派生的类来实现。

virtual 关键字用于修饰方法、属性、索引器或事件声明,并使它们可以在派生类中被重写。例如,此方法可被任何继承它的类重写。

说说抽象类的理解吧:
既然是抽象类,那么就是对事物的抽象描述,它描述的是个体的共性。那马这种动物来说,我们所说的马就是一个抽象类。世界上存在很多种马,白马,黑马,红马......如果没有抽象的概念,我们就没法获得世界上所有马,因为我们要说马的时候,必须指定是哪种马!但是我们其实是有抽象的概念的,我们定义了马这样的一个概念,用来指代世界上所有的马。但马在这个世界上并不是真实存在的,你所能看见的马一定是某一种类型的马!

所以说,抽象类就是这样一种类,描述了一种事物的共性,它不能实例化,只能通过它的子类实例化。
抽象方法:抽象方法一定是抽象类里面的,抽象的方法没有主体,就是没有实现代码,它的实现是由子类实现的。如果一个抽象类里面全是抽象方法的画,那么这个类和接口的功能基本就是一致,而抽象类和接口不一样的地方就在于抽象类可以有非抽象的方法。

还是以马类来说:

//一个抽象的马类
public abstract class 马类
{
//长毛这个方法是抽象的方法,因为它的实现
//必须是具体的那种马去实现的
public abstract void 长毛();
//消化这个方法不是抽象的,所有的马
//都按这个方法去消化东西
public void 消化()
{
Console.WriteLine("消化食物");
}
}
public class 红马 : 马类
{
public override void 长毛()
{
Console.WriteLine("我长的是红毛");
}
}
public class 白马 : 马类
{
public override void 长毛()
{
Console.WriteLine("我长的是白毛");
}
}
}

说完了抽象,说说虚方法。
标记为虚方法的方法,可以在子类被重写。也就说子类可以变异。还是马类为例:

public abstract class 马类
{
//长毛这个方法是抽象的方法,因为它的实现
//必须是具体的那种马去实现的
public abstract void 长毛();
//消化这个方法是虚方法,所有的马
//都按这个方法去消化东西,也可以变异
public virtual void 消化()
{
Console.WriteLine("1小时消化1千克食物");
}
}
public class 红马 : 马类
{
public override void 长毛()
{
Console.WriteLine("我长的是红毛");
}
//在这里变异了,消化能力超强
public override void 消化()
{
Console.WriteLine("1小时消化1吨食物");
}
}

在这里要说明一点是隐藏与重写的区别。

重写:继承时发生,在子类中重新定义父类中的方法,子类中的方法和父类的方法是一样的

隐藏:在派生类中使用new声明一个跟父类一样的方法,那么父类的方法将被隐藏起来,但是还是存在的,可以用base来调用。这样相当于子类有两套名称一样的方法。
C#中,抽象类可以包含虚方法虚方法是在基类中定义的,允许在继承该基类的派生类中重写的方法,使用关键字`virtual`定义。 ### 使用 虚方法抽象类中使用时,在基类中要有具体的实现。在派生类中,可以选择是否对虚方法进行重写。若不重写,调用派生类实例的该虚方法时,使用的是基类定义的方法;若重写,调用派生类实例的该虚方法时,使用的是派生类重写后的方法。示例代码如下: ```csharp public abstract class Animal { // 定义虚方法 public virtual void Speak() { Console.WriteLine("动物发出声音"); } } public class Dog : Animal { // 重写虚方法 public override void Speak() { Console.WriteLine("汪汪汪"); } } public class Cat : Animal { // 不重写虚方法 } class Program { static void Main() { Dog dog = new Dog(); dog.Speak(); // 输出: 汪汪汪 Cat cat = new Cat(); cat.Speak(); // 输出: 动物发出声音 } } ``` ### 特点 - **关键字**:使用`virtual`关键字定义[^1][^2][^3]。 - **方法体**:必须有方法体,即有具体的实现代码[^2]。 - **重写规则**:允许在派生类中使用`override`关键字进行重写,但不是强制要求。若派生类不重写,调用时使用基类的实现;若重写,则使用派生类的实现[^1][^3][^5]。 - **声明位置**:可以在任何非密封类中声明,包括抽象类[^2]。 ### 相关知识 虚方法抽象方法不同,抽象方法使用`abstract`关键字定义,只能在抽象类中声明,且没有具体的实现,派生类必须使用`override`关键字重写抽象方法。在设计时,如果需要提供默认实现并且允许子类选择是否重写,建议使用虚方法;如果需要强制子类提供具体的实现,建议使用抽象方法[^1][^2][^3][^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值