继承与多态

继承与多态

一。继承简介,基本语法

1.基本语法

(1)创建类A:class A:
{}
(2)继承于类A的B:class B:
{}

2.继承有什么用

(1)子类对象可以使用父类的字段和函数,没有重名的情况下,可以直接使用字段或者函数进行访问。
(2)子类对象可以对父类的字段进行修改,对父类的字段、函数进行重写需要用new修饰符。
(下面的例子二维点类派生了三维点类)

    public class Point //基类
    {
        public int x, y;
        public Point(int x, int y)
        {
            this.x = x;
            this.y = y;
        }
        public void  Print()
        {
            Console.WriteLine("我是一个二维下的点坐标");
            Console.WriteLine("{0},{1}", x, y);
        }
    }

    public class Point3D : Point//继承
    {
        public int z;
        public Point3D(int x, int y, int z) : //使用base构造基类
            base(x, y)
        {
            this.z = z;
        }
        public new  void  Print()//new修饰符隐藏基类的Print函数,不加new不hi报错,但会有一个警告。最好还是加上把
        {
            Console.WriteLine("我是一个三维下的点坐标");
            Console.WriteLine("{0},{1},{2}", x, y, z);
        }
    }

    class 类继承
    {
        static void Main(string[] args)
        {
            Point point1 = new Point(1, 2);
            point1.Print();
            Point3D point2 = new Point3D(1, 2,3);
            point2.Print();
            Console.ReadLine();
        }
    }

二。关于继承时的构造函数和base关键字的用法

1.构造函数

(1)父类的构造函数无参时子类在使用构造参数时会自动调用。
(2)父类的构造函数有参数时在子类中需要手动指定参数,例如上面的在子类的构造参数后面需要有:base(参数)

2.base用法(相当于python和java中的super关键字)

通过new操作符的修饰的字段、方法会把父类的字段、方法隐藏。因此通过base.字段或方法来访问。
例如在上面的例子中new修饰符把基类Point的Print方法隐藏,我们可通过super方法对它这个方法进行访问。

public new  void  Print()
        {
            base.Print(); //成功访问父类的print方法。
            Console.WriteLine("我是一个三维下的点坐标");
            Console.WriteLine("{0},{1},{2}", x, y, z);
        }

三。多态性

1.virtual,override关键字介绍。

只是把上面的例子中基类中Print声明为virtual,子类中的声明为override。表示对他的重写,并去掉new。表面上执行的效果以前一模一样。

 public class Point //基类
    {
        public int x, y;
        public Point(int x, int y)
        {
            this.x = x;
            this.y = y;
        }
        virtual public void  Print()
        {
            Console.WriteLine("我是一个二维下的点坐标");
            Console.WriteLine("{0},{1}", x, y);
        }
    }

    public class Point3D : Point//继承
    {
        public int z;
        public Point3D(int x, int y, int z) :
            base(x, y)
        {
            this.z = z;
        }
        override public void  Print()
        {
            Console.WriteLine("我是一个三维下的点坐标");
            Console.WriteLine("{0},{1},{2}", x, y, z);
        }
    }

    class 类继承
    {
        static void Main(string[] args)
        {
            Point point1 = new Point(1, 2);
            point1.Print();
            Point3D point2 = new Point3D(1, 2,3);
            point2.Print();
            Console.ReadLine();
        }
    }

2.多态性是什么?

(1)对第一次、第二次的代码主函数中写以下的部分。很容易发现,我们第二次的两个类更符合我们的设想,因为我们创建的是Point和Point3D类的对象。
虽然我们声明的时候都是以基类Point声明的,但是我们创建对象的时候是用不同的类。这就叫类型的转化。可以把子类转化为用父类表示,因为变量内部存储的是对象地址,存储父类地址的空间也可用于存储子类。


            Point point1 = new Point(1, 2);
            point1.Print();
            Point point2 = new Point3D(1, 2, 3);
            point2.Print();

这是第一次的代码效果
这是第二次的代码效果
(2)有上面的例子我们可一看见virtual和override关键字修饰的类可以和类型的转换搭配使用,我们在不知道以后这个变量要存储哪种类型的对象时,可以先申请一种它父类类型的空间。
(3)多态性:就是申请了同种类型的指针调用相同的方法差生了不同的结果,就像第二图中所示。
(4)注意:用new和override函数修饰的方法要与父类中完全相同。

抽象类

(1)概念:可以把这个类看作是一种特殊的类,这种类不能创建对象,他只有被继承才有实在的意义。因此不能把它声明为sealed(密封类)
(2)从一个实际例子来看:我们先定义一个类:Animal,是动物一定就有吃这个方法,但是每种动物吃的东西不一样。食草动物吃草,食肉动物吃肉

abstract class Animal
    {
        public abstract void Eat();
    }
    class EatMeatAnimal:Animal
    {
        public override void Eat()
        {
            Console.WriteLine("吃肉");
        }
    }
    class EatGrassAnimal : Animal
    {
        public override  void Eat()//override必须写
        {
            Console.WriteLine("吃草");
        }
    }
    class 抽象类抽象方法
    {

        static void Main1(string[] args)
        {
            //抽象类不能创建对象
            Animal m = new EatMeetAnimal();
            Animal g = new EatGrassAnimal();
            m.Eat();
            g.Eat();
            Console.ReadLine();
        }
    }

在这里插入图片描述
3.可以看到声明的语法。
(1)父类用abstract修饰,并且有至少一个函数也被abstract修饰并且只有函数头部。
(2)子类中用override方法用来重写
(3)抽象类的子类如果没有重写抽象方法,则子类也是一个抽象类。

四。接口

1.背景:C#只提供单继承,我们如果想要实现多继承,怎么办?接口就是我们的解决方法
2.通过抽象类的学习,我们发现抽象类是不是非常的鸡肋,声不声明有什么用?只不过不允许抽象类本身创建对象。接口可以完全取代抽象类。既然不让创建创建一个animal类,你就不要写这个类了,你写了还不让我用,你说你贱不贱。
3.语法
(1)interface 接口名
{函数头部}
(2)class 类: 接口名
(3)一个类可以使用多个接口,但只可以继承一个类。因此我们把想要实现的函数可以都放在接口中。
4.把animal声明为接口。

interface Animal
    {
         void Eat();
    }
    class EatMeetAnimal:Animal
    {
        public  void Eat()
        {
            Console.WriteLine("吃肉");
        }
    }
    class EatGrassAnimal : Animal
    {
        public  void Eat()//override必须写
        {
            Console.WriteLine("吃草");
        }
    }
    class 接口
    {

        static void Main(string[] args)
        {
            //接口就不是类
            Animal m = new EatMeetAnimal();
            Animal g = new EatGrassAnimal();
            m.Eat();
            g.Eat();
            Console.ReadLine();
        }`.
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值