文章大纲
加载中...

C#教程4:抽象和接口

3/29/2025 233 阅读
C#教程4:抽象和接口

一、抽象(Abstraction)

抽象是面向对象编程的核心概念,它允许我们关注对象的本质特征,忽略非必要细节。在C#中,抽象主要通过以下关键字实现:

1. abstract 关键字

  • 用于声明抽象类和抽象方法
  • 抽象类不能被直接实例化
  • 抽象方法没有实现,必须由派生类重写

2. virtual 关键字

  • 用于声明可被子类重写的方法
  • 虚方法有默认实现,子类可以选择重写

3. override 关键字

  • 用于重写基类的虚方法或抽象方法
  • 必须与基类方法有相同的签名和返回类型

代码示例:

using System;
// 抽象类:形状Shape
public abstract class Shape
{
    // 普通属性
    public string Color { get; set; }
    // 普通方法
    public void SetColor(string color)
    {
        Color = color;
        Console.WriteLine($"设置颜色为:{color}");
    }
    // 虚方法:有默认实现,子类可以选择重写
    public virtual void Display()
    {
        Console.WriteLine($"这是一个{Color}色的形状");
    }
    // 抽象方法:没有实现,子类必须重写
    public abstract double CalculateArea();
}

// 具体类:圆形
public class Circle : Shape
{
    public double Radius { get; set; }
    public Circle(double radius)
    {
        Radius = radius;
    }
    // 重写抽象方法
    public override double CalculateArea()
    {
        return Math.PI * Radius * Radius;
    }
    // 重写虚方法
    public override void Display()
    {
        Console.WriteLine($"这是一个{Color}色的圆,半径为{Radius}");
    }
}

// 具体类:矩形
public class Rectangle : Shape
{
    public double Width { get; set; }
    public double Height { get; set; }
    
    public Rectangle(double width, double height)
    {
        Width = width;
        Height = height;
    }
    
    // 重写抽象方法
    public override double CalculateArea()
    {
        return Width * Height;
    }
    
    // 重写虚方法
    public override void Display()
    {
        Console.WriteLine($"这是一个{Color}色的矩形,宽为{Width},高为{Height}");
    }
}

class Program
{
    static void Main(string[] args)
    {
        // Shape shape = new Shape(); // 错误!抽象类不能被实例化
        
        Circle circle = new Circle(5);
        circle.SetColor("红");
        circle.Display();
        Console.WriteLine($"圆的面积:{circle.CalculateArea():F2}");
        
        Rectangle rectangle = new Rectangle(4, 6);
        rectangle.SetColor("蓝");
        rectangle.Display();
        Console.WriteLine($"矩形的面积:{rectangle.CalculateArea():F2}");
        
        // 使用多态
        Shape shape1 = new Circle(3);
        shape1.SetColor("绿");
        shape1.Display();  // 调用Circle的Display方法
        Console.WriteLine($"形状1的面积:{shape1.CalculateArea():F2}");
        
        Console.ReadKey();
    }
}

二、接口(Interface)

接口定义了一组相关功能的规范,是一种"能力"的抽象。

接口的特点:

  • 使用interface关键字定义
  • 只包含方法、属性、事件或索引器的签名,不包含实现(C# 8.0之前)
  • 一个类可以实现多个接口
  • 接口成员默认为public

代码示例:

using System;

// 定义接口:可绘制的
public interface IDrawable
{
    void Draw();
    string Description { get; }
}

// 定义接口:可移动的
public interface IMovable
{
    void MoveTo(int x, int y);
    int X { get; set; }
    int Y { get; set; }
}

// 实现单个接口
public class Text : IDrawable
{
    public string Content { get; set; }
    
    public string Description => $"文本:{Content}";
    
    public void Draw()
    {
        Console.WriteLine($"绘制文本:{Content}");
    }
}

// 实现多个接口
public class Button : IDrawable, IMovable
{
    public string Label { get; set; }
    public int X { get; set; }
    public int Y { get; set; }
    
    public string Description => $"按钮:{Label} 位置:({X},{Y})";
    
    public void Draw()
    {
        Console.WriteLine($"绘制按钮:{Label} 在位置 ({X},{Y})");
    }
    
    public void MoveTo(int x, int y)
    {
        X = x;
        Y = y;
        Console.WriteLine($"移动按钮到位置 ({X},{Y})");
    }
}

class Program
{
    static void Main(string[] args)
    {
        // 创建对象
        Text text = new Text { Content = "Hello World" };
        Button button = new Button { Label = "确定", X = 10, Y = 20 };
        
        // 调用方法
        text.Draw();
        Console.WriteLine(text.Description);
        
        button.Draw();
        button.MoveTo(30, 40);
        Console.WriteLine(button.Description);
        
        // 使用接口类型
        Console.WriteLine("\n使用接口类型:");
        
        IDrawable[] drawables = new IDrawable[] { text, button };
        foreach (IDrawable drawable in drawables)
        {
            drawable.Draw();
            Console.WriteLine(drawable.Description);
        }
        
        // 接口转换
        foreach (IDrawable drawable in drawables)
        {
            if (drawable is IMovable movable)
            {
                movable.MoveTo(100, 100);
            }
        }
        
        Console.ReadKey();
    }
}

三、抽象类与接口的对比

特性 抽象类 接口
关键字 abstract interface
实例化 不能 不能
实现方法 可以包含实现的方法和抽象方法 只定义方法签名(C# 8.0前)
继承/实现 一个类只能继承一个抽象类 一个类可以实现多个接口
访问修饰符 可以使用各种访问修饰符 成员默认为public
字段 可以包含字段 不能包含字段
构造函数 可以包含构造函数 不能包含构造函数
静态成员 可以包含静态成员 不能包含静态成员(C# 8.0前)

四、何时使用抽象类与接口?

使用抽象类的场景:

  1. 当几个相关的类需要共享代码和数据时
  2. 当需要定义一个基本行为,但部分行为必须由子类来实现时
  3. 当需要在类之间共享非public成员时

使用接口的场景:

  1. 当不相关的类需要共享一个行为时
  2. 当需要支持多重继承时
  3. 当只关心对象能做什么,而不关心如何做时

五、课后作业

作业1:抽象类应用

创建一个表示电器的抽象类Appliance,包含以下内容:

  • 属性:BrandModelPowerStatus(开/关)
  • 方法:TurnOn()TurnOff()
  • 抽象方法:UseFunction()

然后创建至少两个继承自Appliance的具体电器类(如TelevisionRefrigerator),实现各自的UseFunction()方法,并在主程序中演示使用。

作业2:接口应用

设计一个简单的音乐播放系统:

  1. 创建接口IPlayable,包含方法Play()Pause()Stop()和属性Duration
  2. 创建接口IRecordable,包含方法StartRecording()StopRecording()
  3. 创建至少两个类实现这些接口(如MusicPlayer只实现IPlayableVoiceRecorder实现两个接口)
  4. 在主程序中创建这些对象并通过接口类型调用它们的方法

评论 (0)

暂无评论,来发表第一条评论吧!