C# 继承
- C#中继承的基本概念:在C#中,继承是面向对象编程的核心特性,允许从现有类(基类)创建新类(派生类),继承基类的字段和方法,增强代码的可重用性。
- 继承的实现方式:使用
:
符号实现继承,派生类继承基类的成员,支持方法重写和protected
成员的访问。存在单继承、多级继承、分层继承,但C#不支持多重继承。 - 继承的重要性与应用:继承提高代码重用性和可维护性。通过示例说明继承如何在不同形状(如正方形、矩形)的计算中实现代码复用和扩展。
在 C# 中,继承允许我们从现有类创建一个新类。它是面向对象编程(OOP)的一个关键特性。
作为新类创建基础的类被称为基类(父类或超 类)。而新类被称为派生类(子类或子类)。
派生类继承了基类的字段和方法。这有助于 C# 中代码的可重用性。
如何在 C# 中实现继承?
在 C# 中,我们使用 :
符号来执行继承。例如,
class Animal {
// 字段和方法
}
// Dog 继承自 Animal
class Dog : Animal {
// Animal 的字段和方法
// Dog 的字段和方法
}
这里,我们将派生类 Dog
从基类 Animal
继承。Dog
类现在可以访问 Animal
类的字段和方法。
示例:C# 继承
using System;
namespace Inheritance {
// 基类
class Animal {
public string name;
public void display() {
Console.WriteLine("我是一只动物");
}
}
// Animal 的派生类
class Dog : Animal {
public void getName() {
Console.WriteLine("我的名字是 " + name);
}
}
class Program {
static void Main(string[] args) {
// 派生类的对象
Dog labrador = new Dog();
// 访问基类的字段和方法
labrador.name = "Rohu";
labrador.display();
// 访问自己类的方法
labrador.getName();
Console.ReadLine();
}
}
}
输出
我是一只动物
我的名字是 Rohu
在上述示例中,我们从超类 Animal
派生了一个子类 Dog
。注意以下语句,
labrador.name = "Rohu";
labrador.getName();
这里,我们使用 labrador
(Dog 的对象)来访问 Animal
类的 name
和 display()
。这是因为派生类继承了基类的所有字段和方法。
此外,我们还在 Dog
类的方法中访问了 name
字段。
is-a 关系
在 C# 中,继承是一种 is-a 关系。我们只在两个类之间存在 is-a 关系时使用继承。例如,
- Dog(狗 ) 是一种 Animal(动物)
- Apple(苹果) 是一种 Fruit(水果)
- Car(汽车) 是一种 Vehicle(交通工具)
我们可以从 Animal 类派生 Dog。类似地,Apple 可以从 Fruit 类派生,Car 可以从 Vehicle 类派生。
C# 继承中的 protected 成员
当我们将一个字段或方法声明为 protected
时,它只能从同一个类及其派生类中访问。
示例:继承中的 protected 成员
using System;
namespace Inheritance {
// 基类
class Animal {
protected void eat() {
Console.WriteLine("我会吃");
}
}
// Animal 的派生类
class Dog : Animal {
static void Main(string[] args) {
Dog labrador = new Dog();
// 访问基类的 protected 方法
labrador.eat();
Console.ReadLine();
}
}
}
输出
我会吃
在上述示例中,我们创建了一个名为 Animal
的类。该类包含了一个受保护的方法 eat()
。
我们从 Animal
类派生出了 Dog
类。注意这个语句,
labrador.eat();
由于 protected
方法可以在派生类中访问,我们可以在 Dog
类中访问 eat()
方法。
继承的类型
有以下几种类型的继承:
1. 单继承
在单继承中,一个派生类从一个基类继承。
2. 多级继承
在多级继承中,一个派生类从一个基类继承,然后同一个派生类又作为基类为另一个类提供继承。
3. 分层继承
在分层继承中,多个派生类从一个基类继承。
4. 多重继承
在多重继承中,一个派生类从多个基类继承。C# 不支持多重继承。 但是,我们可以通过接口实现多重继承。
5. 混合继承
混合继承是两种或更多类型继承的组合。多级和分层继承的组合就是混合继承的一个例子。
C# 继承中的方法重写
如果基类和派生类中都存在相同的方法,派生类中的方法将重写基类中 的方法。这在 C# 中称为方法重写。例如,
using System;
namespace Inheritance {
// 基类
class Animal {
public virtual void eat() {
Console.WriteLine("我吃食物");
}
}
// Animal 的派生类
class Dog : Animal {
// 重写 Animal 的方法
public override void eat() {
Console.WriteLine("我吃狗粮");
}
}
class Program {
static void Main(string[] args) {
// 派生类的对象
Dog labrador = new Dog();
// 访问重写的方法
labrador.eat();
}
}
}
输出
我吃狗粮
在上述示例中,eat()
方法在基类和派生类中都存在。
当我们使用 Dog
对象 labrador
调用 eat()
时,
labrador.eat();
调用的是 Dog
内部的方法。这是因为 Dog
中的方法重写了 Animal
中的同名方法。
注意,我们分别在基类和派生类的方法中使用了 virtual
和 override
。这里,
virtual
- 允许方法被派生类重写override
- 表明该方法重写了基类的方法
C# 继承中的 base 关键字
在前面的示例中,我们看到派生类中的方法重写了基类中的方法。
但是,如果我们想同时调用基类的方法怎么办?
在这种情况下,我们使用 base
关键字从派生类中调用基类的方法。
示例:C# 继承中的 base 关键字
using System;
namespace Inheritance {
// 基类
class Animal {
public virtual void eat() {
Console.WriteLine("动物吃食物。");
}
}
// Animal 的派生
类
class Dog : Animal {
// 重写 Animal 的方法
public override void eat() {
// 调用 Animal 类中的方法
base.eat();
Console.WriteLine("狗吃狗粮。");
}
}
class Program {
static void Main(string[] args) {
Dog labrador = new Dog();
labrador.eat();
}
}
}
输出
动物吃食物。
狗吃狗粮。
在上述示例中,eat()
方法存在于基类 Animal
和派生类 Dog
中。注意以下语句,
base.eat();
这里,我们使用了 base
关键字从 Dog
类访问 Animal
类的方法。
C# 中继承的重要性
为了理解继承的重要性,让我们考虑一个情况。
假设我们正在处理正多边形,如正方形、矩形等。我们需要根据输入计算这些多边形的周长。
1. 由于计算周长的公式对所有正多边形都是通用的,我们可以创建一个 RegularPolygon
类和一个 calculatePerimeter()
方法来计算周长。
class RegularPolygon {
calculatePerimeter() {
// 计算周长的代码
}
}
2. 并从 RegularPolygon
类继承 Square
和 Rectangle
类。这些类中的每一个都会有属性来存储边长和边数,因为它们对于所有多边形都是不同的。
class Square : RegularPolygon {
int length = 0;
int sides = 0;
}
我们将 length
和 sides
的值传递给 calculateperimeter()
来计算周长。
这就是继承如何使我们的代码可重用和更直观。
示例:继承的重要性
using System;
namespace Inheritance {
class RegularPolygon {
public void calculatePerimeter(int length, int sides) {
int result = length * sides;
Console.WriteLine("周长: " + result);
}
}
class Square : RegularPolygon {
public int length = 200;
public int sides = 4;
public void calculateArea() {
int area = length * length;
Console.WriteLine("正方形的面积: " + area);
}
}
class Rectangle : RegularPolygon {
public int length = 100;
public int breadth = 200;
public int sides = 4;
public void calculateArea() {
int area = length * breadth;
Console.WriteLine("矩形的面积: " + area);
}
}
class Program {
static void Main(string[] args) {
Square s1 = new Square();
s1.calculateArea();
s1.calculatePerimeter(s1.length, s1.sides);
Rectangle t1 = new Rectangle();
t1.calculateArea();
t1.calculatePerimeter(t1.length, t1.sides);
}
}
}
输出
正方形的面积: 40000
周长: 800
矩形的面积: 20000
周长: 400
在上述示例中,我们创建了一个 RegularPolygon
类,它有一个计算正多边形周长的方法。
这里,Square
和 Rectangle
继承自 RegularPolygon
。
计算周长的公式对所有形状都是通用的,因此我们重用了基类的 calculatePerimeter()
方法。
由于计算不同形状的面积的公式不同,我们在派生类中创建了一个单独的方法来计算面积。