面向对象核心概念详解
继承
继承是面向对象程序设计中最重要的核心概念之一。继承允许我们根据一个类来定义另一个类。
当创建一个类时,不需要完全重新编写新的数据成员和函数成员,只需要设计一个新类,继承了已有类的成员即可。这个已有类为基类(父类),这个新类为派生类(子类)
继承的思想实现了属于关系,如狗属于哺乳动物,哺乳动物属于动物,因此狗属于动物
C#不支持多重继承,但支持接口的多重继承,一个类可以实现多个接口。换句话来说一个类可以继承多个接口,但只能继承自一个类
1. 语法实现继承下·
csharp
namespace ConsoleApp1
{
//基类 Animal
class Animal
{
public string? Name { get; set; }
public void Eat()
{
Console.WriteLine($"{Name} is Eating...");
}
}
//派生类
class Dog : Animal
{
public void Bark()
{
Console.WriteLine($"{Name} is Barking...");
}
}
internal class Program
{
static void Main(string[] args)
{
Dog dog1 = new Dog();
dog1.Name = "小黄";//继承自Animal
dog1.Eat();//调用基类方法
dog1.Bark();//调用派生类方法
}
}
}
关键特性
- 单继承: C#只支持单继承(一个类只能继承一个基类)
- 传递性: 继承关系可以传递(Dog=>Animal=>Object)
- 成员继承:派生类自动获取基类的非私有成员
- 构造函数要求:派生类必须调用用基类的构造函数(显示或隐式)
2. base关键字
csharp
我们可以使用base关键字调用基类的构造函数和方法
csharp
namespace ConsoleApp1
{
//基类 Animal
class Animal
{
public string? Name { get; set; }
public int Age { get; set; }
public void Eat()
{
Console.WriteLine($"{Name} is Eating...");
}
public Animal(string nameV,int ageV)
{
Name = nameV;
Age = ageV;
Console.WriteLine("Animal对象已被创建 动物的名字是{0},它有{1}岁了",Name,Age);
}
}
//派生类
class Dog : Animal
{
public void Bark()
{
Console.WriteLine($"{Name} is Barking...");
}
//通过:base调用基类的构造函数并传递name和age参数对基类初始化
public Dog(string name , int age):base(name,age) { }
//通过base关键字调用基类的方法,也可以省略base
public void Met()
{
//base.Eat();
//省略base
Eat();
}
}
internal class Program
{
static void Main(string[] args)
{
Dog dog1 = new Dog("小黄",7);
dog1.Met();
}
}
}
三种主要用法
- 调用基类构造函数给基类初始化 :base(参数)
- 访问基类成员 base.成员名
- 解决命名冲突
重要限制
- 必须在构造函数首行使用
- 不能同时使用this()和base()
- 静态方法中不能使用base
virtual和override关键字重写
方法重写机制
arduino
namespace ConsoleApp1
{
class Shap
{
//通过virtual关键字定义一个虚方法 可被重写
public virtual double CalculateArea()
{
return 0;
}
}
class Circle : Shap
{
public double Radius { get; set; }
//通过override关键字重写CalculateArea方法
public override double CalculateArea()
{
return Math.PI*Radius*Radius;
}
}
class Rectangle : Shap
{
public double width { get; set; }
public double height { get; set; }
//通过override关键字重写CalculateArea方法
public override double CalculateArea()
{
return width*height;
}
}
internal class Program
{
static void Main(string[] args)
{
Circle c = new Circle();//实现多态
c.Radius = 10d;
Rectangle Rect = new Rectangle();//实现多态
Rect.width = 5;
Rect.height = 6;
Console.WriteLine(c.CalculateArea());
Console.WriteLine(Rect.CalculateArea());
}
}
}
关键规则
关键字 | 位置 | 作用 | 是否必须 |
---|---|---|---|
virtual |
基类 | 声明方法可被重写 | 可选 |
override |
派生类 | 提供新实现 | 重写时必须 |
new |
派生类 | 隐藏基类方法 | 可选(不推荐) |
重写vs隐藏
new 关键字可以隐藏基类中的同名成员,此时基类的方法被隐藏你所调用的是派生类的方法(非多态)。也就是说使用new关键字修饰成员后会隐藏同名的基类成员,此时调用的同名成员是派生类的成员而不是基类的成员
csharp
namespace ConsoleApp1
{
class Shap
{
//通过virtual关键字定义一个虚方法 可被重写
public virtual double CalculateArea()
{
return 0;
}
}
class Triangle : Shap
{
public new double CalculateArea()
{
return 1;
}
}
internal class Program
{
static void Main(string[] args)
{
Triangle Tr = new Triangle();
Console.WriteLine(Tr.CalculateArea());//打印1
}
}
}
多态的概念与好处
核心概念
多态:同一操作作用于不同类的实例,产生不同的执行结果。也就是说同一操作在不同类的使用情境下会产生不同的结果
三种实现方式
- 继承多态:通过虚方法重写实现
- 接口多态:通过接口实现
- 参数多态:泛型编程
csharp
public class GraphicsRenderer
{
// 多态方法:可处理任何Shape派生类
public void Render(Shape shape)
{
double area = shape.CalculateArea(); // 多态调用
Console.WriteLine($"Rendering shape with area: {area}");
}
}
// 使用
var renderer = new GraphicsRenderer();
renderer.Render(new Circle(5)); // 输出圆面积
renderer.Render(new Rectangle(3,4)); // 输出矩形面积
总结:结成体系的核心价值
