理解Java的多态性
public class ShapeShower {
public static void main(String[] args) {
Shape s = new Shape();s.draw();//Shape Draw
System.out.println("=========================");
s = new Triangle();s.draw();//Shape Draw
//Triangle里面啥都没有,这里竟然没有编译错误!
System.out.println("=========================");
s = new Square();s.draw();//Square Draw
System.out.println("=========================");
s = new Circle();s.draw();//Circle Draw
//s.radius = 9 //编译错误,只提供了函数的动态绑定
//正确代码:
((Circle)s).radius = 9;//父类转子类,要强制转换
System.out.println("=========================");
s = new LittleCircle();s.draw();//LittleCircle Draw
}
}
class Shape{ void draw(){System.out.println("Shape Draw");}}
class Triangle extends Shape{}
class Square extends Shape{ void draw(){System.out.println("Square Draw");}}
class Circle extends Shape{
public int radius;
void draw(){ System.out.println("Circle draw");}
}
class LittleCircle extends Circle{
void draw() { System.out.println("LittleCircle Draw");}
}
工资系统
理解Java的多态和方法的重写
假设某企业有四类员工:
1、领固定周薪的员工;
2、按销售额提成的员工;
3、带底薪且按销售额提成的员工;(+15%的底薪)
4、小时工(若一周工时>40h,还要对额外的工时支付额外50%的加班费);
所有员工父类
因而要设计成抽象类
//所有员工的父类,因而要设计为抽象类
public abstract class Employee {
private String name;
private String ID;
public Employee(String name,String ID){
this.name = name;
this.ID = ID;
}
//================= getter and setter================
public void setName(String name){ this.name = name;}
public String getName(){ return this.name; }
public void setID(String ID){ this.ID = ID; }
public String getID(){ return this.ID; }
//================= getter and setter================
public String toString(){
return String.format("%s:%s\n%s:%s\n","员工姓名",getName(),"工号",getID());
}
//声明抽象方法!!!!所有员工都用该方法结账
public abstract double earnings();
}
周薪员工 类
public class SalariedEmployee extends Employee{
private double weeklySalary;
public SalariedEmployee(String name,String ID,double salary){
super(name,ID);
setWeeklySalary(salary);
}
//================= getter and setter================
public void setWeeklySalary(double weeklySalary) {
this.weeklySalary = weeklySalary;
}
public double getWeeklySalary(){
return this.weeklySalary;
}
//================= getter and setter================
public double earnings() {
return getWeeklySalary();
}
public String toString(){
return String.format("周薪员工工资:\n %s %s:%.2f",
super.toString(),"工资",getWeeklySalary());
}
}
注意:如果下面这个方法不写出来,这个类会一直报错
public double earnings() {
return getWeeklySalary();
}
按销售额提成的员工 类
public class CommissionEmployee extends Employee{
private double grossSales;//销售额
private double commissionRate;//提成率
public CommissionEmployee(String name,String ID,double sales,double rate){
super(name,ID);
setCommissionRate(rate);
setGrossSales(sales);
}
//================= getter and setter================
public double getGrossSales() {return grossSales;}
public void setGrossSales(double grossSales) {
this.grossSales = grossSales;
}
public double getCommissionRate() {return commissionRate;}
public void setCommissionRate(double commissionRate) {
this.commissionRate = commissionRate;
}
//================= getter and setter================
public double earnings(){
return getCommissionRate() * getGrossSales();
}
public String toString(){
return String.format("%s:\n%s\n%s:%.2f %s:%.2f\n",
"按销售额提成的员工工资",super.toString(),
"销售额",getGrossSales(),"提成率",getCommissionRate());
}
}
小时工 类
package FifthClass_2.SalarySystem;
public class HourlyEmployee extends Employee{
private double hourlyWage;//每小时工资
private double hours;//工时
public HourlyEmployee(String name,String ID,double wage,double workHours){
super(name, ID);
setHourlyWage(wage);
setHours(workHours);
}
//================= getter and setter================
public double getHourlyWage() {return hourlyWage;}
public void setHourlyWage(double hourlyWage) {
this.hourlyWage = hourlyWage;
}
public double getHours() {return hours;}
public void setHours(double hours) {
this.hours = hours;
}
//================= getter and setter================
public double earnings(){
if(getHours() <= 40){return getHours()*getHourlyWage();}
else
return 40*getHourlyWage()+(getHours()-40)*getHourlyWage()*1.5;
}
public String toString(){
return String.format("小时工工资:\n %s%s:%.2f\n%s:%.2f",
super.toString(),"每小时工资",getHourlyWage(),"工时",getHours());
}
}
带底薪并且按销售额提成的员工 类
继承按销售额提成的员工类
package FifthClass_2.SalarySystem;
public class BasePlusCommissionEmployee extends CommissionEmployee{
private double baseSalary;//底薪
public BasePlusCommissionEmployee(String name,String ID,double sales,double rate,double salary){
super(name,ID,sales,rate);
setBaseSalary(salary);
}
public double getBaseSalary() {
return baseSalary;
}
public void setBaseSalary(double baseSalary) {
this.baseSalary = baseSalary;
}
public double earnings(){
return getBaseSalary()*1.15 + super.earnings();
}
public String toString(){
return String.format("底薪加提成员工工资:%s底薪:%.2f",super.toString(),getBaseSalary());
}
}
测试类
package FifthClass_2.SalarySystem;
//理解Java的多态和方法的覆盖(重写)
/*
假设某企业有四类员工:
1、领固定周薪的员工;
2、按销售额提成的员工;
3、带底薪且按销售额提成的员工;(+15%的底薪)
4、计时工(若一周工时>40h,还要对额外的工时支付加班费);
*/
public class Test {
public static void main(String[] args) {
SalariedEmployee employee1 =
new SalariedEmployee("员工1","001",1000);
HourlyEmployee employee2 =
new HourlyEmployee("员工2","002",99,40);
CommissionEmployee employee3 =
new CommissionEmployee("员工3","003",30000,.06);
BasePlusCommissionEmployee employee4 =
new BasePlusCommissionEmployee("员工4","004",1000,.04,300);
System.out.println("员工工资情况如下:\n");
System.out.println(String.format("%s\n%s:%.2f\n\n",employee1,"工资",employee1.earnings()));
System.out.println(String.format("%s\n%s:%.2f\n\n",employee2,"工资",employee2.earnings()));
System.out.println(String.format("%s\n%s:%.2f\n\n",employee3,"工资",employee3.earnings()));
System.out.println(String.format("%s\n%s:%.2f\n\n",employee4,"工资",employee4.earnings()));
}
}
运行结果:
抽象类、抽象方法
抽象类无法被实例化
抽象方法没有具体实现
子类必须重写父抽象类的方法
其作用在于:
- 抽象类的作用是让其子类来继承它所定义的属性及方法,以避免各子类重复定义这些相同的内容。程序员可以先建立抽象类(定义子类共有的属性及方法),再从一般类派生出具体性质的子类。
- 抽象类用于描述抽象的概念,抽象方法仅声明方法的参数和返回值,抽象方法的具体实现由抽象类的子类完成,子类必须覆盖(重写)父类的抽象方法。
- 抽象类的抽象方法约定了多个子类共用的方法声明,每个子类可以根据自身实际情况,给出抽象方法的具体实现,显然不同的子类可以有不同的方法实现。因此,一个抽象方法再多个子类中表现出多态性。
import java.awt.*;
abstract class Paint{
Color c;
Color getColor(){
System.out.println("Paint getColor");
return c;
}
//抽象方法
abstract void draw();
}
class Drawing extends Paint{
//实现抽象类
void draw(){
System.out.println("Drawing Draw\n");
}
}
public class AbstractClass {
public static void main(String[] args) {
Paint s;
s = new Drawing();
//抽象类无法被实例化,只能转换为子类类型
s.draw();//Drawing Draw
s.getColor();//Paint getColor
}
}
接口
比抽象类还抽象的类
1. 成员变量只能是常量
2. 方法的修饰符default、static、abstract在同一个方法声明中不能同时出现
3. default方法、static方法必须有方法体
4. 接口中所有的抽象方法都隐含为public abstract方法,所有的常量都隐含为public static final方法。
5. 接口使Java具有了多重继承的能力,可以实现类implements多个接口
package FifthClass_2.Interface;
public interface Interface {
double PI = 3.14;
double area();
default void Print1(){
System.out.println("接口的default方法");
}
static void Print2(){
System.out.println("接口的static方法");
}
}
实现接口的类
- 实现接口的类要么为抽象类,要么实现接口的抽象方法
- 实现接口的抽象方法时,必须要是public
public class Implement implements Interface{
int r;
public double area(){
return PI * r * r;
}
}