抽象可以通过抽象类或接口来实现。

abstract关键字用于类和方法:

  • 抽象类:是一个受限类,不能用于创建对象(要访问它,必须从另一个类继承)。
  • 抽象方法:只能在抽象类中使用,并且它没有主体。主体即具体实现由派生类(继承自)提供。

抽象类可以有抽象方法和实现方法,至少有一个抽象方法。

试图讲一个抽象类Employee来实例化,错题提示如下;

  •  示例:员工工资统计程序

现在有四类员工:

  1. 固定薪水员工 2.计时员工 3.提成员工 4.底薪+提成员工

经过分析知道:

1.所有员工都有一些共同的信息,【姓名】【工号】这两个作为字段成员,一个抽象Earning()方法作为计算薪酬,一个重写的toString()来显示基本信息;

所有定义一个抽象类,作为上述4类员工的基类,包含2个成员变量,1个构造函数,1个重写的overide string ToString()方法:

 /// <summary>
    /// 基类Employee
    /// </summary>
    public abstract class Employee//创建抽象的基类
    {
        protected Employee(string name, string ssd)//构造函数
        {
            Name = name;
            SSD = ssd;
        }
        public string Name { get;private set; }
        public string SSD { get;private set; }
        public override string ToString()//重写方法
        {
            return string.Format($"姓名:{Name}\n工号:{SSD}");
        }
        public abstract decimal Earning();//抽象方法
    }

2.接下来,定义第一个固定薪酬员工类,它将继承自上述的Employee基类,固定薪酬员工,它相比基类多了一个薪酬monthSalary,作为字段成员,并为其创建属性,注意在set时使用private修饰,表示为私有,不可外部修改;构造方法,值得注意的事需要也把继承自基类的参数name和ssd采用 :base(name,ssd)赋值;

 /// <summary>
    /// 1固定薪水员工
    /// </summary>
    public class MonthEmployee:Employee
    {
        private decimal monthSalary;
        public decimal MonthSalary//属性
        {
            get
            { return monthSalary; }
            set
            { monthSalary = value > 0 ? value : 0; }//注意这里的选择表达式是冒号:
        }
        public MonthEmployee(string name, string ssd, decimal salary):base(name,ssd)//构造函数
        {
            MonthSalary = salary;
        }
        public override decimal Earning()
        {
            return MonthSalary;
        }
        public override string ToString()
        {
            return string.Format($"定薪员工>>\n{base.ToString()}\n工资:{MonthSalary:C}");
        }
    }

3.同上,定义第2类员工:计时员工,它相比基类多了2个字段,1个是小时工资,1个是工作时厂,代码如下:

 /// <summary>
    ///2 时薪员工
    /// </summary>
    public class HourlyEmployee:Employee
    {
        private double hours;
        private decimal hourSalary;

        public HourlyEmployee(string name,string ssd,double hours, decimal hourSalary):base(name,ssd)
        {
            this.hours = hours;
            this.hourSalary = hourSalary;
        }

        public double Hours { get { return hours; } private set { hours = value > 0 ? value : 0; } }//属性1
        public decimal HourSalary
        { get { return hourSalary; } private set{hourSalary = value > 0 ? value : 0; }}//属性2

        public override decimal Earning()
        {
            if (hours <= 40)
            {
                return hourSalary * (decimal)hours;
            }
            else
            {
                return 40 * hourSalary + (decimal) (hours - 40) * hourSalary*1.5M;//超过40H加班费
            }
        }
        public override string ToString()
        {
            return string.Format($"时薪员工>>\n{base.ToString()}\n工时:{Hours}\n工资:{Earning():C}");
        }
    }

4.同上,定义第3类员工:提成员工,它相比基类多了2个字段,1个是销售额,1个是提成比例,代码如下:

 /// <summary>
    /// 3提成员工
    /// </summary>
    public class SaleEmployee : Employee
    {
        private decimal sale;
        private decimal saleRatio;
        public decimal Sale { get { return sale; }private set { sale = value > 0 ? value : 0; } }
        public decimal SaleRatio { get { return saleRatio; } private set { saleRatio = value > 0 ? value : 0; } }
        public SaleEmployee(string name, string ssd, decimal sale, decimal saleRatio) : base(name, ssd)
        {
            this.Sale = sale;
            this.SaleRatio = saleRatio;
        }
        public override decimal Earning()
        {
            return sale * saleRatio;
        }
        public override string ToString()
        {
            return string.Format($"提成员工>>\n{ base.ToString()}\n销售额:{sale}\n工资:{Earning()}");
        }
    }

5.接下来,定义第4类员工底薪+提成员工,此类员工在上述提成员工的基础上,外加了一部分底薪;所以,此类派生自上述SaleEmployee类;但他多了一个字段底薪;

/// <summary>
    /// 4底薪提成员工
    /// </summary>
    public class BaseSaleEmployee : SaleEmployee
    {
        private decimal baseSalary;
        public decimal BaseSalary { get { return baseSalary; } private set { baseSalary = value > 0 ? value : 0; } }
        public BaseSaleEmployee(string name, string ssd, decimal sale, decimal saleRatio,decimal baseSalary) : base(name, ssd,sale,saleRatio)
        {
            this.BaseSalary = baseSalary;
        }
        public override decimal Earning()
        {
            return Sale * SaleRatio+baseSalary;
        }
        public override string ToString()
        {
            return string.Format($"底薪+提成员工>>\n{ base.ToString()}\n底薪:{baseSalary}");
        }
    }

如此,4类员工+1个抽象基类员工全部定义设计完成。在VS中,可以在类视图选中右键如下图所以,查看类图(PS:如果右键没有这个选项功能,是vs缺少安装组件,参考连接:VS 2019如何查看类图_@2206的博客-CSDN博客_vs查看类图

 最后:在主程序演示使用以上类;

 1    class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             var EP1 = new MonthEmployee("王猛","1111",800M);
 6             var EP2 = new HourlyEmployee("李毅", "2222", 70,20M);
 7             var EP3 = new SaleEmployee("张宇", "3333", 15070, 0.05M);
 8             var EP4 = new BaseSaleEmployee("赵雄", "4444", 17070, 0.04M,500);
 9 
10             Employee[] emp = new Employee[4];
11             emp[0] = EP1; emp[1] = EP2; emp[2] = EP3; emp[3] = EP4;
12 
13             Console.WriteLine("===============如下是数组打印内容=============");
14             int i = 0;
15             foreach (var item in emp)
16             {
17                 i++;
18                 Console.WriteLine(item);
19                 Console.WriteLine("-----------------------{0}-----------------------", i);
20             }
21             Console.ReadLine();
22         }
23     }

输出结果:

 

 至此,抽象类与派生类的学习总结完成。

最后,感谢B站的免费视频和视频中西安交大的崔老师;链接:C#程序设计 西安交通大学 C#基础入门教程_哔哩哔哩_bilibili

^(* ̄(oo) ̄)^祝大家学习愉快!