C#学习笔记——(18)多态

a 夏天 提交于 2020-01-31 02:44:01

基本概念

抽象类和抽象方法

声明抽象类的格式

public abstract class 抽象类名
{
   声明类中的各个成员
}

抽象方法

[访问修饰符] abstract 返回值类型 方法名 ([参数列表]);

如果一个类是抽象类的话不能进行实例化,只能作为继承。如果一个类里有抽象方法,则此类不能实例化。

override和overload

override(从写)
如果基类中有一个抽象的函数,在派生中给出了具体实现的代码,则称为override。发生在父类和子类之间,父类有一个方法,子类从写了。
overload(从载)
一般发生在同一个类中,指两个方法具有同样的名称,但是具有不同的参数列表。如果仅仅返回值不同,不作为区分的参考。

virtual

成员字段和静态方法不能是virtual。

sealed(密封)

sealed类不允许继承,sealed方法不允许重写。

运算符重载(operator)
public static 返回值类型 operator 运算符([形参表列])
{
   函数体
}

例题-多态的演示(以圆、球体和圆柱为例)

多态实现的条件

1、必须在基类和继承类中出现,即基类为public class Circle,继承类定义public class Sphere:Circle,必须与基类有关系;
2、把发生多态的方法(个人理解即在基类和继承类中的函数名称一样),在基类的函数中标记为virtual public virtual double Area(),继承类中标记为override public override double Area()

using System;
//多态的演示
namespace ConsoleApplication6
{
    class Program
    {
        static void Main(string[] args)
        {
            Circle c1 = new Circle(1);
            Console.WriteLine(Area(c1));
            Sphere s1 = new Sphere(1);
            Console.WriteLine(Area(s1));
            Cylinder cy1 = new Cylinder(1, 1);
            Console.WriteLine(Area(cy1));
        }
        //对于多态在基类的面积前面加virtual,派生类中加override,可以调用正确版本的函数
        static double Area(Circle c)    
        {
            return c.Area();
        }
    }
    public class Circle         //定义一个基类
    {
        protected double radius;
        public Circle(double r)  //构造函数,初始化radius
        {
            radius = r >= 0 ? r : 0;
        }
        public virtual double Area()   //为了多态
        {
            return Math.PI * radius * radius;
        }
    }
    public class Sphere:Circle  //派生一个球体的类
    {
        public Sphere(double r) : base(r) { } //构造函数
        public override double Area()
        {
            return Math.PI * radius * radius * 4;
        }
    }
    public class Cylinder:Circle     //派生一个圆柱体的类
    {
        protected double height;
        public Cylinder(double r,double h):base(r)  //构造函数
        {
            height = h >= 0 ? h : 0;
        }
        public override double Area()
        {
            return 2 * Math.PI * radius * radius + 2 * Math.PI * height * radius;
        }
    }
}

例题-Abstract关键字的使用(宠物类)

在这个例子中,宠物是基类,猫和狗是继承类,定义不同的动物叫声不同,由于宠物整体不能定义叫声,因此不能够创建实例,所以要使用abstract类型 public abstract void Speak(); 这个不需要有具体的内部函数,在主函数中就直接跳过不会显示。具体到猫和狗则会分情况而发出相应的叫声。需要注意的是在基类定义时也需要定义为abstract类型 public abstract class Pet 因为一个abstract类才能够有abstract类型的函数。

using System;
//Abstract关键字的使用
namespace ConsoleApplication6
{
    class Program
    {
        static void Main(string[] args)
        {
            //Pet p1 = new ConsoleApplication6.Pet("Pet", 3);  抽象类不能创建实例
            //Speak(p1);
            Cat c = new Cat("Jack", 3);
            Dog d = new Dog("Bool", 4);
            Speak(c);
            Speak(d);
        }
        static void Speak(Pet p)
        {
            Console.WriteLine(p);
            p.Speak();
            if(p is Cat)    //is运算符的使用
            {
                Console.WriteLine("This is Cat");
            }
        }
    }
    public abstract class Pet   // 抽象基类
    {
        public string Name { get; private set; }   //get读取名字是public的,设置名字是private
        public int Age { get; private set;}
        public Pet(string n,int a)     //构造函数
        {
            Name = n;
            Age = a;
        }
        //抽象的方法不再具有函数体,由于宠物是一个实例
        //宠物没有办法定义怎么叫,所以写成abstract类型,而不是virtual类型
        public abstract void Speak();   
        public override string ToString()
        {
            return Name;
        }
    }
    public class Cat:Pet
    {
        public Cat(string n,int a) : base(n, a) { }
        public override void Speak()
        {
            Console.WriteLine("MIAOMIAO");
        }
    }
    public class Dog:Pet
    {
        public Dog (string n,int a) : base(n, a) { }
        public override void Speak()
        {
            Console.WriteLine("WANGWANG");
        }
    }
}

例题-运算符重载(使用+代替加法Add)

using System;
//Abstract关键字的使用
namespace ConsoleApplication6
{
    class Program
    {
        static void Main(string[] args)
        {
            Complex x1 = new Complex(1, 2);
            Complex x2 = new Complex(2, 3);
            Complex x3 = x1.Add(x2);
            Complex x4 = x1 + x2;   //重新定义了加号的含义,使得可以直接这样写
            Console.WriteLine(x3);
            Console.WriteLine(x4);
        }
    }
    public class Complex
    {
        private double real;
        private double image;
        public Complex(double r,double i)
        {
            real = r;
            image = i;
        }
        public void Set(double r,double i)
        {
            real = r;
            image = i;
        }
        public override string ToString()
        {
            return String.Format("{0}+{1}i", real, image);   //string中的合成函数
        }
        public Complex Add(Complex x)
        {
            Complex t = new ConsoleApplication6.Complex(0, 0);
            t.real = x.real + real;
            t.image = x.image + image;
            return t;
        }
        public static Complex operator +(Complex x1,Complex x2)   //运算符的重载,必须是静态
        {
            Complex t = new ConsoleApplication6.Complex(0, 0);
            t.real = x1.real + x2.real;
            t.image = x1.image + x2.image;
            return t;
        }
    }
}

例题-接口

using System;
//Abstract关键字的使用
namespace ConsoleApplication6
{
    class Program
    {
        static void Main(string[] args)
        {

        }
    }
    public interface IPortA   //一般以I开头表示接口
    {
        void DisplayA();   //所有接口的方法都没有具体的函数体
    }
    public interface IPortB:IPortA  //接口可以继承
    {
        void DisplayB();
    }
    public class AA:IPortB
    {
        public void DisplayA()    //写类时要先写出实现两个接口的函数,才能够成功继承
        {
            Console.WriteLine("IPortA");
        }
        public void DisplayB()
        {
            Console.WriteLine("IPortB");
        }
    }
}

例题-员工工资(综合)

using System;
//员工工资
namespace Example04
{
    class Program
    {
        static void Main(string[] args)
        {
            Employee[] employees = new Employee[4];  //创建一个具有四个元素的数组
            employees[0] = new SalariedEmployee("Jhon", "111-111-111", 800M);
            employees[1] = new HourEmployee("Karen", "222-222-222", 16.78M, 39M);
            employees[2] = new CommissionEmployee("Sue", "333-333-333", 10000M, 0.05M);
            employees[3] = new BasePlusCommissionEmployess("Bob", "444-444-444", 20000M, 0.05M, 300M);
            //foreach遍历数组
            foreach (var currentEmployee in employees) //foreach (Employee currentEmployee.....
            {
                Console.WriteLine(currentEmployee);
                Console.WriteLine(currentEmployee.Earn());
            }
        }
    }
    abstract class Employee   //基类
    {
        public string Name { get; private set; }
        public string SSD { get; private set; }
        public Employee(string name, string ssd)
        {
            Name = name;
            SSD = ssd;
        }
        public override string ToString()
        {
            return string.Format("Name:{0},ID:{1}", Name, SSD);
        }
        public abstract decimal Earn();
    }
    class SalariedEmployee : Employee   //第一个继承类,固定员工
    {
        private decimal weekSalary;   //提供变量
        public decimal WeeSalary      //创建变量属性
        {
            get { return weekSalary; }
            set { weekSalary = value > 0 ? value : 0; }
        }
        public SalariedEmployee(string name, string ssd, decimal wSalary)
            : base(name, ssd)
        {
            WeeSalary = wSalary;
        }
        public override decimal Earn()
        {
            return WeeSalary;
        }
        public override string ToString()
        {
            return string.Format("SalayeEmployee: {0}\n{1:C}",
                base.ToString(), WeeSalary);
        }
    }
    class HourEmployee : Employee   //第二个继承类:小时工
    {
        private decimal hour;
        private decimal wage;
        public decimal Hour    //创建变量属性
        {
            get { return hour; }
            set { hour = value > 0 ? value : 0; }
        }
        public decimal Wage
        {
            get { return wage; }
            set { wage = value > 0 ? value : 0; }
        }
        public HourEmployee(string name, string ssd, decimal w, decimal h)   //构造函数
            : base(name, ssd)
        {
            Wage = w;
            Hour = h;
        }
        public override decimal Earn()   //计算工资
        {
            if (Hour <= 40)
            {
                return Hour * Wage;
            }
            else
            {
                return Wage * 40 + (Hour - 40) * 1.5M * Wage;   //1.5后面加M表明是decimal的数字
            }
        }
        public override string ToString()
        {
            return string.Format("HourlyEmployee:{0} \n HourlyWage:{1:C} " +
                "HoursWorked {2}", base.ToString(), Wage, Hour);
        }
    }
    class CommissionEmployee : Employee  //第三个继承类:销售
    {
        private decimal grossSale;       //总销售额
        private decimal commissionRate;  //提成百分比
        public decimal GrossSale
        {
            get { return grossSale; }
            set { grossSale = value > 0 ? value : 0; }
        }
        public decimal CommissionRate
        {
            get { return commissionRate; }
            set { commissionRate = value > 0 ? value : 0; }
        }
        public CommissionEmployee(string name, string ssd, decimal g, decimal c)
            : base(name, ssd)   //构造函数
        {
            GrossSale = g;
            commissionRate = c;
        }
        public override decimal Earn()   //从写Earn函数(每个继承类不一样)
        {
            return CommissionRate * GrossSale;
        }
        public override string ToString()   //字符串显示信息
        {
            return string.Format("CommissionEmployee {0} \n " +
                "GrossSale: {1:C} Rate{2}", base.ToString(), GrossSale, CommissionRate);
        }
    }
    class BasePlusCommissionEmployess : CommissionEmployee   //第四个继承类:基于底薪的类,从CommissionEmployee派生的
    {
        private decimal baseSalary;
        private decimal BaseSalary
        {
            get { return baseSalary; }
            set { baseSalary = value > 0 ? value : 0; }
        }
        public BasePlusCommissionEmployess(string name, string ssd, decimal g,
            decimal c, decimal b) : base(name, ssd, g, c)    //构造函数
        {
            BaseSalary = b;
        }
        public override decimal Earn()   //从写函数
        {
            return base.Earn() + BaseSalary;
        }
        public override string ToString() //字符输出
        {
            return string.Format("BasePlusCommissionEmployess:{0}\n" +
                "BaseSalary{1:C}", base.ToString(), BaseSalary);
        }
    }
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!