C#笔记进阶篇01 类的继承

本文是C#进阶笔记的第一部分,详细介绍了类的继承,包括基类与派生类的概念,Object类,派生类的访问,使用new关键字和base关键字处理成员重名问题,以及继承的特性。同时探讨了里氏替换原则及其在代码设计中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

C#笔记进阶篇01 类的继承

——本系列是基于人民邮电出版社《C#2008 C#图解教程》、清华大学出版社《C#入门经典(第五版)》两本书的自学C#笔记,如果您发现了本文的纰漏,还望不吝指正。

写在前边:

封装、继承、多态,是面向对象的三大特性。所以继承是面向对象程序设计中最重要的概念之一

1. 基类和派生类

任何类都可以从另一个类中继承,这就是说,这个类拥有它继承的类的所有成员。在OOP(Object-Oriented Programming,即面向对象编程)中,被继承(也称为派生)的类称为父类(也称为基类)。注意,C#中的对象仅能直接派生于一个基类,当然基类也可以有自己的基类。——清华大学出版社《C#入门经典(第五版)》

用一个已存在的类去定义出一个新的类

  • 新的类叫做 子类/派生类

  • 已存在的类叫做 父类/基类/超类

声明方法:访问修饰 class 派生类名:基类名{ }

例:创建一个Person类,一个Studunt类派生自Person

class Person
{
    public string name;
    public int age;
    public char sex;
    public Person(string name, int age, char sex)
    {
        this.name = name;
        this.age = age;
        this.sex = sex;
    }
    public void SayHallo() 
    {
        Console.WriteLine("大家好,我是{0},今年{1},性别{2}",name,age,sex);
    }
}
class Student : Person 
{
    public string major;
    //子类的构造函数中需要继承的参数需要使用base关键字
    public Student(string name, int age, char sex, string major): base(name,age,sex)    
    {
        this.major = major;
    }
    public new void SayHallo() 
    {
        base.SayHallo();
        Console.WriteLine("我的专业是:"+major);
    }
}

2. Object类

除了特殊的Object类,所有的类都是派生类,即使它们没有基类规格说明。
C#中所有类的最终基类都是Object类,如下图所示
1-1

3. 派生类的访问

派生类中继承而来的成员可以被访问,就像它们是派生类自己声明的一样。
例:下面的代码声明类SomeClass和它的派生类OtherClass

class SomeClass
{
	public string Field1 ="base class field";
	public void Method1(string value)
	{
		Console.WriteLine("Base class --Method1:{0}",value);
	}
}
class OtherClass:SomeClass
{
	public string Field2 ="derived class field";
	public void Method2(string value)
	{
		Console.WriteLine("Derived class --Method2:{0}",value);
	}
}
class Program
{
		static void Main()
		{
			OtherClass oc = new OtherClass();
			oc.Method1(oc.Field1);
			oc.Method1(oc.Field2);
			oc.Method2(oc.Field1);
			oc.Method2(oc.Field2);
		}
}

控制台输出结果:
————————————————————————————————————————————————————
Base class – Methood1:base class field
Base class – Methood1:derived class field
Derived class – Methood2:base class field
Derived class – Methood2:derived class field

4. 使用new关键字掩盖基类的成员

如果子类中有成员与父类中的成员重名,可以用new关键字为子类中这个成员申请一个新的空间,以便于计算机识别,(如果不写,也将默认掩盖基类,只是编辑器会有警告)
例:下边的代码中,派生类OtherClass使用new关键字掩盖基类的成员

class SomeClass
{
	public string Field1 ="base class field";
	public void Method1(string value)
	{
		Console.WriteLine("Base class --Method1:{0}",value);
	}
}
class  OtherClass:SomeClass
{
	new public string Field1 ="other class field1";
	new public void Method1(string value)
	{
		Console.WriteLine("Other class --Method1:{0}",value);
	}
}
class Program
{
		static void Main()
		{
			OtherClass oc = new OtherClass();
			oc.Method1(oc.Field1);
		}
}

控制台输出结果:
————————————————————————————————————————————————————
Other class --Method1:other class field1

5. 使用base关键字访问基类

在上边的例子中,派生类OtherClass使用new关键字掩盖了基类的变量成员Field1和函数成员Method1(string value),可以使用基类访问表达式来访问基类中被隐藏的成员。

  • 基类访问表达式:base.成员名称

在上边的代码中,在派生类中增加代码

class  OtherClass:SomeClass
{
	new public string Field1 ="other class field1";
	new public void Method1(string value)
	{
		Console.WriteLine("Other class --Method1:{0}",value);
		Console.WriteLine(base.Field1);
		base.Method1(base.Field1);
	}
}

控制台输出结果:
————————————————————————————————————————————————————
Other class --Method1:other class field1
base class field
Base class --Method1:base class field

6. 继承的特性

1).一个类只可以直接继承于一个基类
2).派生类拥有基类的所有属性和方法
3).派生类不能访问基类的私有成员,但可以访问其公共成员
4).子类会默认调用父类的默认构造函数
5).如果父类的默认构造函数失效,子类需要重新指定(使用base关键字)
6).如果一个类没有父类,将默认继承Object类
7).类和结构体的默认访问修饰符:internal 本程序集
8).只有派生类才能访问protected 成员,外部代码不能访问。

扩展:里氏替换原则

SOLID,面向对象设计的五个基本原则:单一功能原则、开闭原则、里氏替换原则、接口隔离原则以及依赖倒置原则

子类可以扩展父类的功能,但不能改变父类原有的功能。它包含以下4层含义:

  • 子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法。
  • 子类中可以增加自己特有的方法。
  • 当子类的方法重载父类的方法时,方法的前置条件(即方法的形参)要比父类方法的输入参数更宽松。
  • 当子类的方法实现父类的抽象方法时,方法的后置条件(即方法的返回值)要比父类更严格。
    作者:侠客8090
    链接:https://www.jianshu.com/p/93259a886427
    来源:简书

将子类当作父类去使用(因为子类拿到了父类的所有内容)或是将父类对象显示转换为子类对象使用

使用is/as关键字,在基类,派生类之间进行尝试转换:

  • is:判断这个变量是否能转换成对应类型,如果可以,返回true,否则返回false;
  • as: 尝试转换,如果能,返回转换过后的对象,如果不能,返回null

例:接文章最开始的代码,创建一个Person类,一个Studunt类派生自Person

static void Main()
{
    Person wangwu = new Student("王五", 20, '男', "C#");
    wangwu.SayHallo(); //以人类对象的身份做自我介绍
    Person zhangsan = new Person("张三", 18, '男');
    zhangsan.SayHallo();
    
    //里式替换
    if (wangwu is Student) 
    {
        (wangwu as Student).SayHallo(); //以学生对象的身份做自我介绍
    }
     if (zhangsan is Student)         //尝试转换失败,返回null
    {
        (zhangsan as Student).SayHallo();
    }
}

控制台输出结果:
————————————————————————————————————————————————————
大家好,我是王五,今年20,性别男
大家好,我是张三,今年18,性别男
大家好,我是王五,今年20,性别男
我的专业是:C#

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值