我们定义了一个抽象类Shape
,其中包含抽象方法Draw()
,子类Rectangle
和Circle
分别实现了这个抽象方法。
抽象类Animal
中定义了虚方法MakeSound()
,派生类Dog
选择重写这个虚方法。
接口IShape
声明了方法Draw()
,类Square
实现了该接口。
在Main
方法中,我们创建了相应的对象并调用它们的方法,实现了多态性的效果
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp5
{
// 抽象类
public abstract class Shape
{
public abstract void Draw(); // 抽象方法,子类需实现
}
// 继承自抽象类的子类
public class Rectangle : Shape
{
public override void Draw()
{
Console.WriteLine("Drawing a rectangle.");
}
}
// 继承自抽象类的子类
public class Circle : Shape
{
public override void Draw()
{
Console.WriteLine("Drawing a circle.");
}
}
// 基类
public class Animal
{
public virtual void MakeSound() // 虚方法,子类可重写
{
Console.WriteLine("The animal makes a sound.");
}
}
// 继承自基类的子类
public class Dog : Animal
{
public override void MakeSound()
{
Console.WriteLine("The dog barks.");
}
}
// 接口
public interface IShape
{
void Draw(); // 方法声明
}
// 实现了接口的类
public class Square : IShape
{
public void Draw()
{
Console.WriteLine("Drawing a square.");
}
}
internal class Program
{
static void Main(string[] args)
{
Shape shape = new Rectangle(); // 抽象类和子类的示例
shape.Draw(); // 输出:Drawing a rectangle.
Animal animal = new Dog(); // 基类和子类的示例
animal.MakeSound(); // 输出:The dog barks.
IShape square = new Square(); // 接口和实现类的示例
square.Draw(); // 输出:Drawing a square.
}
}
}
抽象方法、虚方法和接口都是面向对象编程中实现多态性的重要概念,它们有以下区别和用途:
- 抽象方法(Abstract Methods):
- 声明方式:抽象方法是在抽象类中声明的方法,使用
abstract
关键字修饰,并且没有实现体。 - 继承和实现:抽象类可以包含抽象方法,子类必须实现(
override
)抽象方法。 - 特点:抽象方法必须在抽象类中才能声明,抽象类本身不能被实例化。
- 用途:抽象方法通常用于定义基础类的行为,强制子类实现具体细节。
- 2.虚方法(Virtual Methods):
- 声明方式:虚方法是在基类中声明的方法,使用
virtual
关键字修饰,并且有默认的实现体。 - 继承和重写:派生类可以选择性地重写(
override
)虚方法,也可以直接使用基类中的默认实现。 - 特点:虚方法可以在基类中有默认的实现,但是也可以被派生类覆盖以提供新的实现。
- 用途:虚方法用于定义基类的默认行为,但允许派生类对其行为进行修改。
- 3.接口(Interfaces):
- 声明方式:接口定义了一组成员(方法、属性、事件),使用
interface
关键字声明,成员没有实现体。 - 继承和实现:一个类可以实现一个或多个接口,接口成员必须在实现类中实现。
- 特点:接口只定义成员,不包含实现的细节。
- 用途:接口用于定义一组行为契约,让实现类自行决定每个成员的具体实现。
选择抽象类、虚方法或接口取决于需求。
如果需要提供默认实现并允许子类进行修改,则使用虚方法;
如果需要定义基类的行为,但要求子类必须实现特定方法,则使用抽象方法;
如果需要定义一组行为契约,不关心具体实现,则使用接口。
总结:
- 抽象方法是在抽象类中声明的,没有实现体,必须在其子类中实现。
- 虚方法是在基类中声明的,有默认实现,可以被子类选择性地重写。
- 接口是一组成员的声明,没有实现体,实现类必须提供这些成员的具体实现。