C#核心之面向对象-继承

面向对象-继承

在这里插入图片描述

1、继承的基本规则

1、基本概念
一个类A继承一个类B
    类A将会继承类B的所有成员
    A类将拥有B类的所有特征和行为
被继承的类
    称为父类、基类、超类
继承的类
    称为子类。派生类
    子类可以有自己的特征和行为
特点
    1、单根性 子类只能有一个父类
    2、传递性 子类可以间接继承父类的父类
2、基本语法
class 类名 : 被继承的类名{}
3、示例
TeachingTeacher tt = new TeachingTeacher();
tt.name = "亮亮老师";
tt.number = 1;
tt.SpeakName();
tt.subject = "Unity";
tt.SpeakSubject();

class Teacher
{
    public string name;
    public int number;

    public void SpeakName()
    {
        Console.WriteLine(name);
    }
}

class TeachingTeacher : Teacher
{
    public string subject;
    public void SpeakSubject()
    {
        Console.WriteLine(subject + "老师");
    }
}
4、访问修饰符的影响
public 公共 内外部访问
private 私有 内部访问 //子类可以通过父类方法间接访问私有成员
protected 保护 内部和子类访问
internal 内部 只有在同一个程序集的文件中,内部类或者成员才可以访问
5、子类和父类的同名成员

概念:C#中允许子类存在和父类同名的成员,但不建议这样做

2、里氏替换原则

1、基本概念
里氏替换原则是面向对象七大原则中最重要的原则
概念:
    任何父类出现的地方,子类都可以替代
重点:
    语法表现-父类容器装子类对象,因为子类对象包含了父类的所以内容
作用:
    方便进行对象存储和管理
2、is和as
基本概念
    is:判断一个对象是否是指定类对象
   		返回值:bool 是为真,不是为假
    as:将一个对象转换为指定类对象
    	返回值:指定类对象
    	成功返回指定类型对象,失败返回null
基本语法:
    类对象 is 类名
    	该语句块会有一个bool返回值 true 和 false
    类对象 as 类名
    	该语句块会有一个对象返回值 对象和null
3、基本实现
//里氏替换原则 用父类容器装载子类对象
GameObject player = new Player();
GameObject monster = new Monster();
GameObject boss = new Boss();

GameObject[] objects = { player, monster, boss };

if(player is Player)
{
    //Player p = player as Player;
    //p.PlayerAtk();
    (player as Player).PlayerAtk();
}

for(int i = 0; i < objects.Length; i++)
{
    if (objects[i] is Player)
    {
        (objects[i] as Player).PlayerAtk();
    }
    else if (objects[i] is Monster)
    {
        (objects[i] as Monster).MonsterAtk();
    }
    else if (objects[i] is Boss)
    {
        (objects[i] as Boss).BossAtk();
    }
}
class GameObject
{

}
class Player : GameObject
{
    public void PlayerAtk()
    {
        Console.WriteLine("玩家攻击");
    }
}
class Monster : GameObject
{
    public void MonsterAtk()
    {
        Console.WriteLine("怪兽攻击");
    }
}
class Boss : GameObject
{
    public void BossAtk()
    {
        Console.WriteLine("Boss攻击");
    }
}

3、继承中的构造函数

1、基本概念
特点
    当声明一个子类对象时
    先执行父类的构造函数   //执行顺序
    再执行子类的构造函数
注意
    父类的无参构造很重要
    子类可以通过base关键字代表父类,调用父类构造
2、父类的无参构造函数

子类实例化时,默认自动调用父类的无参构造

3、通过base调用指定父类构造
class Father{public Father(int i){}}
class Son : Father{
    public Son(int i) : base(i){}
    public Son(int i, sting str):this(i){}
}

4、万物之父和装箱拆箱

1、万物之父
关键字	object
概念
    object是所有类型的基类,它是一个类(引用类型)
作用
    1、可以利用里氏替换原则,用object容器装所有对象
    2、可以用来表示不确定类型,作为函数参数类型
2、万物之父使用
引用类型
    用is as 来判断和转换
    class son{Speak(){}}
    object o = new Son();
    if(o is son)
    {
        (o as son).Speak();
    }
值类型
    用强转
    object o = 1.1f;
	float f = (float)o;
string
    object str = "123abc";
	string str1 = str.ToString;
	string str2 = str as string;
数组
    object arr = new int[10];
    int[] arr1 =(int[])arr;
	int[] arr1 =arr as int[];
3、装箱拆箱
发生条件
    用object存值类型(装箱)
    再把object转为值类型(拆箱)
装箱
    把值类型用引用类型存储
    栈内存会迁移到堆内存中
拆箱
    把引用类型存储的值类型取出来
    堆内存会迁移到栈内存中
好处:不确定类型时可以方便参数的存储和传递
坏处:存在内存迁移,增加性能消耗

5、密封类

1、基本概念

密封类是使用sealed密封关键字修饰的类
作用:让类无法再被继承

2、示例

sealed class Father{}
class Son : Father{}

3、作用

再面向对象程序设计中,密封类的主要作用就是不允许最底层子类被继承
可以保证程序的规范性、安全性
思考 载具类上下车
//定义一个载具类
//有速度,最大速度,可乘人数,司机和乘客,有上车,下车方法
//用载具类声明一个对象,并将若干人装载上车

Car car = new Car(10, 20, 20);
Driver driver = new Driver();
car.GetIn(driver);
Passenger passenger1 = new Passenger();
car.GetIn(passenger1);
Passenger passenger2 = new Passenger();
car.GetIn(passenger2);
Passenger passenger3 = new Passenger();
car.GetIn(passenger3);
car.GetOff(passenger2);
class Person { }
class Driver : Person { }
class Passenger : Person { }
class Car
{
    public int speed;
    public int maxSpeed;
    public int num;
    public Person[] persons;
    public Car(int speed, int maxSpeed, int num)
    {
        this.speed = speed;
        this.maxSpeed = maxSpeed;
        this.num = 0;  //实际人数
        persons = new Person[num];
    }
    public void GetIn(Person p)
    {
        if (num >= persons.Length)
        {
            Console.WriteLine("满载");
            return;
        }
        persons[num] = p;
        num++;
    }
    public void GetOff(Person p)
    {
        for (int i = 0; i < persons.Length; i++)
        {
            if (persons[i] == null)
            {
                break;
            }
            if (persons[i] == p)
            {
                //移动位置
                for (int j = i; j < num - 1; j++)
                {
                    persons[j] = persons[j + 1];
                }
                //最后一个位置清空
                persons[num - 1] = null;
                num--;
                break;
            }
        }
    }
}

相关推荐

  1. 【python】python面向对象——继承

    2024-05-04 09:20:04       24 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-05-04 09:20:04       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-05-04 09:20:04       101 阅读
  3. 在Django里面运行非项目文件

    2024-05-04 09:20:04       82 阅读
  4. Python语言-面向对象

    2024-05-04 09:20:04       91 阅读

热门阅读

  1. C语言结课总结与示例代码

    2024-05-04 09:20:04       33 阅读
  2. Centos 常见的命令

    2024-05-04 09:20:04       36 阅读
  3. CMakeLists.txt 简单地语法介绍

    2024-05-04 09:20:04       33 阅读
  4. Electron试用 SQLite

    2024-05-04 09:20:04       38 阅读
  5. 华为试题之删除最少字符

    2024-05-04 09:20:04       31 阅读
  6. sqlalchemy单条记录查询函数对比

    2024-05-04 09:20:04       34 阅读
  7. 优化SQL的方法

    2024-05-04 09:20:04       38 阅读