[C#]——接口与继承

一、. 接口 interface ------ C++ 纯虚基类的「升级版」

C++ 里你想要「只定规矩、不定实现」会用纯虚基类:

复制代码
// C++:纯虚基类 = 接口
class Ishape
{
public:
    virtual ~Ishape() = default;  //c++习惯:虚析构
    virtual double Area() const= 0;    // 纯虚函数 = 0
    virtual void Print() const= 0;    
}


//c#interface 自带【抽象】属性,不用写virtual 、不用=0
Interface   Ishape
{
 public:
     double Area();      //默认抽象,分号结尾
     void Print();    
}

1.1 C++ vs C# 对照表

|----------|--------------------------|----------------------|
| 维度 | C++ 纯虚基类 | C# interface |
| 关键字 | class + = 0 | interface(独立关键字) |
| 成员默认 | 普通函数,需手写 virtual ... = 0 | 自动抽象,不写 virtual |
| 访问修饰 | 自己写 public: | 一律 public,不能写 public |
| 字段(数据成员) | 可以有 | 不能有(只能有方法/属性/事件) |
| 多继承 | 可以,但容易钻石继承 | 类可实现多个接口,天然解冲突 |
| 虚析构 | 必须手写 virtual ~Foo() | 不需要(C# 有 GC,没这坑) |

1.2 三个关键规则(C# 特有,C++ 没有的约定)

1、接口名约定用 I 开头:IShape、IDrawable、IComparable。这是 .NET 的硬约定,C++ 没这规矩。

2、接口里不能写字段,但可以写「属性」------属性本质是方法嘛:

interface IAnimal

{

string Name { get; set; } // ✅ 属性,本质是两个方法 get_/set_

// int age; // ❌ 编译错误,接口不能有字段

}

3、类可以实现多个接口(这是 C# 比 C++ 多继承更优雅的地方,后面练习会演示)。


二、继承语法 : ------ C# 用一个冒号通吃

C++ 继承要写访问修饰:class Dog : public Animal。

C# 不用,一个冒号搞定,因为 C# 只有 public 继承(没有 private/protected 继承那套)。

复制代码
//c++
class Cricle : public Ishape{};

//c# --冒号后面直接跟基类/接口
class Cricle : Ishape{}             //实现接口
class Dog : Animal{}                //继承类
class Bagle :Animal,IFlyable,IComparable{}     //一个基类 + 多个接口

⚠️ 规则:基类只能有一个(C# 不允许多继承类),接口可以有任意多个。基类要写在最前面。

调用基类构造:base(...) ≈ C++ 的 Base(...)

复制代码
// C++:初始化列表调基类构造
class Dog : public Animal {
public:
    Dog(string n) : Animal(string n)       //基类构造
};


// C#:base(...) 相当于 C++ 初始化列表
// C++:初始化列表调基类构造
class Dog : Animal {

  public  Dog(string n) : base(string n)       //调用animal的构造函数
};

三、 is / as ------ C# 版的 dynamic_cast

这是 C++ 转 C# 最容易对应上的点。C++ 你用 dynamic_cast 做运行时类型转换:

复制代码
// C++:dynamic_cast

IShape* s = new Circle(2);
Circle* c = dynamic_cast<Circle*>(s); // 失败返回nullptr
if(dynamic_cast<Rectangle*>(s))       // 判断是不是某个类型
{

}

C# 拆成两个更直观的关键字:

|-----------------------------------|--------|--------------------------|
| C++ | C# | 干什么 |
| dynamic_cast<T*>(p) != nullptr | p is T | 判断:是不是这个类型,返回 bool |
| dynamic_cast<T*>(p) | p as T | 转换:能转就给对象,不能转给 null(不抛异常 |

复制代码
// C++ as
Ishape s = new Cricle(2);
if(s is Rectangle){}                   //false
Circle c = s as Cricle;                // 成功->Circle对象
Rectangle r = s as Rectangle;          // 失败 → null,不崩

小提示:C# 7+ 还有个更顺手的 if (s is Circle c) ------判断+转换+变量名一步到位,后面练习里我会用到。

复制代码
using System;
using System.Collections.Generic;


interface IShapes
{
    double Area();
    void Print();
}

interface IDrawable
{
    void Draw();
}


class Circle : IShapes, IDrawable        // 冒号 + 接口列表,一个类实现多个接口
{
    public double Radius { get; }
    public Circle(double radius)
    {
        Radius = radius;
    }
    public double Area() => 3.14 * Radius * Radius;
    public void Print() => Console.WriteLine($"圆的半径 ={Radius}面积={Area():F2}");
    public void Draw() => Console.WriteLine($"  画一个圆 ○ (半径 {Radius})");

}
class Rectangle : IShapes                // 只实现 IShape
{
    public double width { get; }
    public double Length { get; }

    public Rectangle(double w, double h)
    {
        width = w;
        Length = h;
    }
    public double Area() =>  width * Length;
    public void Print() => Console.WriteLine($"矩形长宽 ={width}x{Length} 面积={Area():F2}");
}

class Animal
{
    public string Name { get; }
    public Animal(string name) => Name = name;
    public virtual void Speak() => Console.WriteLine($"{Name}: ...");
}

class Dog : Animal
{
    public Dog(string name) : base(name) { }   // base(...) ≈ C++ 初始化列表
    public  override void Speak()=> Console.WriteLine($"{Name}: DOGDOG");
}
class Program
{
    static void Main()
    {
        // 用接口类型装具体对象 ------ 这就是多态的雏形
        // C++ 等价:vector<IShape*> shapes;
        List<IShapes> shapes = new()
        {
            new Circle(3),
            new Rectangle(4, 5),
            new Circle(1),
            new Rectangle(2, 3)
        };

        Console.WriteLine("===== 所有图形 =====");
        double total = 0;
        foreach(var s in shapes)
        {
            s.Print();
            total += s.Area();
        }
        Console.WriteLine($"面积={total:F2}");


        // is / as:把圆单独挑出来(≈ C++ dynamic_cast)
        Console.WriteLine("===== 挑出圆,打印半径 =====");
        foreach(var s in shapes)
        {
            if(s is Circle c)
            {
                Console.WriteLine($"招到圆,圆的半径={c.Radius}");
                c.Draw();                // 圆实现了 IDrawable,可以调
            }
        }


        //as 用法
        Console.WriteLine();
        IShapes first = shapes[0];
        Rectangle r = first as Rectangle;
         // 继承 demo
        Console.WriteLine("\n===== 继承 demo =====");
        Animal a = new Dog("wangcai");
        a.Speak();
    }
}
相关推荐
冻柠檬飞冰走茶1 小时前
PTA基础编程题目集 7-17 爬动的蠕虫(C语言实现)
c语言·开发语言·数据结构·算法
咯哦哦哦哦1 小时前
qt creator x86交叉编译arm 配置
开发语言·qt
乐启国际旅行社有限公司2 小时前
Java线程池实战:文旅系统批量任务性能优化(团期生成/数据导出)
java·开发语言·性能优化
宸津-代码粉碎机2 小时前
告别手动Jar部署!生产级无损热部署方案,彻底解决OOM与更新失效问题
java·大数据·开发语言·人工智能·python
米码收割机2 小时前
【移动】线上购物移动端网站(源码+文档)【独一无二】
java·开发语言·前端·python·django
小肝一下2 小时前
多态(上)
android·开发语言·c++·vscode·多态·面向对象·伊蕾娜
无敌秋2 小时前
python/c++/java上云
java·c++·python
code_pgf12 小时前
C++11 / C++14 / C++17 / C++20 新特性总结
c++·c++20
魔力女仆12 小时前
分享一个 JS 鼠标跟随贪吃蛇背景库
开发语言·javascript·计算机外设