多态的三种手段

用virtual修饰的方法叫做虚方法 虚方法可以在子类中通过override关键字来重写 常见的虚方法:ToString() Equalsc#基础多态的三种手段

多态的概念概念:让一个对象能够表现出多种的状态(类型)

实现多态的3种手段:1、虚方法 2、抽象类 3、接口

关于虚方法需要注意的几点:
1.父类中如果有方法需要让子类重写,则可以将该方法标记为virtual
2.虚方法在父类中必须有实现,哪怕是空实现。
3.虚方法子类可以重写(override),也可以不重写


关于抽象方法注意的几点:
1.需要用abstract关键字标记
2.抽象方法不能有任何方法实现。
3.抽象成员必须包含在抽象类中。
4.由于抽象成员没有任何实现,所以子类必须将抽象成员重写。
5.抽象类不能实例化,
抽象类的作用:抽象类的作用就是为了让子类继承。
6.抽象类中可以包括抽象成员,可以包括有具体代码的成员。
7. 还有抽象方法不能用static修饰

1.接口中只能包含方法(属性、事件、索引器也都是方法)
2.接口中的成员都不能有任何实现。光说不做
3.接口不能被实例化。
4.接口中的成员不能有任何访问修饰符。(默认为public)
5.实现接口的子类必须将接口中的所有成员全都实现。
6.子类实现接口的方法时,不需要任何关键字,直接实现即可。
7.接口存在的意义就是为了多态。

//1.虚方法

用virtual修饰的方法叫做虚方法
虚方法可以在子类中通过override关键字来重写
常见的虚方法:ToString() Equals

 

//1)、虚方法
//步骤:
//1、将父类的方法标记为虚方法 ,使用关键字 virtual,这个函数可以被子类重新写一个遍。


public class Employee { public virtual void DaKa() { Console.WriteLine("九点打卡"); } } public class Manager : Employee { public override void DaKa() { Console.WriteLine("经理11点打卡"); } } public class Programmer : Employee { public override void DaKa() { Console.WriteLine("程序猿不打卡"); } }
//抽象类1

//2)、抽象类
//当父类中的方法不知道如何去实现的时候,可以考虑将父类写成抽象类,将方法写成抽象方法。


抽象类与抽象方法由abstract修饰
abstract的使用注意
抽象方法没有方法体
抽象成员只能存在于抽象类中
抽象类可以有非抽象成员
抽象类的派生类必须实现抽象方法体
抽象类只能用作基类,无法实例化


public abstract class Animal//抽象类 { public virtual void T() { Console.WriteLine("我是虚方法"); //如果父类中的方法有默认的实现,并且父类需要被实例化,这时可以考虑将父类定义成一个普通类,用虚方法来实现多态。 // 如果父类中的方法没有默认实现,父类也不需要被实例化,则可以将该类定义为抽象类。 } //6.在抽象类中可以包含实例成员。 // 并且抽象类的实例成员可以不被子类实现 private int _age; public int Age { get { return _age; } set { _age = value; } } public Animal(int age) { this.Age = age; } public abstract void Bark();//抽象方法 1.抽象成员必须标记为abstract,并且不能有任何实现。 public abstract string Name//抽象属性 { get; set;// //4. 抽象属性 子类继承抽象类后,必须把父类中的所有抽象成员都重写。 } // public abstract string TestString(string name); //2.抽象成员必须在抽象类中。 //3.抽象类不能被实例化 public Animal() { } //public void Test() //{ // //空实现 //} } public abstract class Test : Animal { //(除非子类也是一个抽象类,则可以不重写) } public class Dog : Animal//alt +shirt+F10 { // public abstract void Test(); public override void Bark() { Console.WriteLine("狗狗旺旺的叫"); } public override string Name { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } } //string //public override string TestString(string name) //{ // //throw new NotImplementedException(); //} //如果父类的抽象方法中有参数,那么。继承这个抽象父类的子类在重写父类的方法的时候必须传入对应的参数。 //如果抽象父类的抽象方法中有返回值,那么子类在重写这个抽象方法的时候 也必须要传入返回值。 }
//抽象类2
 public abstract class Shape
    {
        public abstract double GetArea();
        public abstract double GetPerimeter();
    }

 public abstract class Shape
    {
        public abstract double GetArea();
        public abstract double GetPerimeter();
    }

 public class Circle : Shape
    {

        private double _r;
        public double R
        {
            get { return _r; }
            set { _r = value; }
        }

        public Circle(double r)
        {
            this.R = r;
        }
        public override double GetArea()
        {
            return Math.PI * this.R * this.R;
        }

        public override double GetPerimeter()
        {
            return 2 * Math.PI * this.R;
        }
    }
    public class Square : Shape
    {
        private double _height;

        public double Height
        {
            get { return _height; }
            set { _height = value; }
        }

        private double _width;

        public double Width
        {
            get { return _width; }
            set { _width = value; }
        }

        public Square(double height, double width)
        {
            this.Height = height;
            this.Width = width;
        }

        public override double GetArea()
        {
            return this.Height * this.Width;
        }

        public override double GetPerimeter()
        {
            return (this.Height + this.Width) * 2;
        }
    }

1.抽象成员必须标记为abstract,并且不能有任何实现。
2.抽象成员必须在抽象类中。
3.抽象类不能被实例化

4.子类继承抽象类后,必须把父类中的所有抽象成员都重写。

(除非子类也是一个抽象类,则可以不重写)
5.抽象成员的访问修饰符不能是private
6.在抽象类中可以包含实例成员。
并且抽象类的实例成员可以不被子类实现

7.抽象类是有构造函数的。虽然不能被实例化。


8、如果父类的抽象方法中有参数,那么。继承这个抽象父类的子类在重写父类的方法的时候必须传入对应的参数。

如果抽象父类的抽象方法中有返回值,那么子类在重写这个抽象方法的时候 也必须要传入返回值。


======
如果父类中的方法有默认的实现,并且父类需要被实例化,这时可以考虑将父类定义成一个普通类,用虚方法来实现多态。

如果父类中的方法没有默认实现,父类也不需要被实例化,则可以将该类定义为抽象类。


接口

接口是一种规范。
只要一个类继承了一个接口,这个类就必须实现这个接口中所有的成员为了多态。 接口不能被实例化。

也就是说,接口不能new(不能创建对象)

接口中的成员不能加“访问修饰符”,接口中的成员访问修饰符为public,不能修改。

(默认为public) 接口中的成员不能有任何实现(“光说不做”,只是定义了一组未实现的成员)。

接口中只能有方法、属性、索引器、事件,不能有“字段”和构造函数。

接口与接口之间可以继承,并且可以多继承。

接口并不能去继承一个类,而类可以继承接口 (接口只能继承于接口,而类既可以继承接口,也可以继承类)

实现接口的子类必须实现该接口的全部成员。

一个类可以同时继承一个类并实现多个接口,如果一个子类同时继承了父类A,并实现了接口IA,那么语法上A必须写在IA的前面。

class MyClass:A,IA{},因为类是单继承的。显示实现接口的目的:解决方法的重名问题

什么时候显示的去实现接口:
当继承的借口中的方法和参数一摸一样的时候,要是用显示的实现接口

当一个抽象类实现接口的时候,需要子类去实现接口。

 public interface IFlyable
    {
        //接口中的成员不允许添加访问修饰符 ,默认就是public
        void Fly();
        string Test();
        //不允许写具有方法体的函数

     //   string _name;//不能含字段
         string Name
        {
            get;//自动属性
            set;
        }
    
    }

                             //为了多态。
           // 接口不能被实例化。
          //也就是说,接口不能new(不能创建对象)
            IFlyable fly1 = new Bird();


 //显示实现接口就是为了解决方法的重名问题
            IFlyable fly = new Bird();
            IFlyable FLY1 = new Bird();
            fly.Fly();
            Bird bird = new Bird();
            bird.Fly();



public class Bird : IFlyable
    {
        public void Fly()
        {
            Console.WriteLine("鸟飞会");
        }
        /// <summary>
        /// 显示实现接口
        /// </summary>
        // void IFlyable.Fly()
        //{
        //    Console.WriteLine("我是接口的飞");
        //}
        void IFlyable.Fly() { Console.Write("我是接口的飞"); }     

    }

  public interface IFlyable
    {
        void Fly();
    }
原文地址:https://www.cnblogs.com/liuweiqiang11188/p/6677605.html