【连载】Java学习系列(007)——继承和多态

来源:互联网 发布:支付系统网络硬件架构 编辑:程序博客网 时间:2024/06/05 18:04

Java学习系列(007)——继承和多态

  1. 继承:(inheritance):从已有的类创建新类的过程。提供继承信息的类叫父类(超类、基类),得到继承信息的类叫子类(派生类、衍生类)。
    • is-a关系,子类is-a(是一个)父类
    • 子类要继承父类的属性,其属性应该使用protected修饰
  2. 多态:(polymorphism):执行相同的行为却做了不同的事情(产生了不同的结果)。
    • 方法重写(在继承过程中)
    • 对象造型(将子类造型成父类)
  3. 抽象:(abstraction):寻找共性。定义类的过程就是一个抽象的过程,需要做数据抽象和行为抽象。

    • 抽象类不能实例化,专门用来让别的类继承它,如果一个类中有抽象方法,那么该类必须被申明为抽象类。
  4. 相关概念

    • 抽象类:被abstract关键字修饰的类,抽象类不能实例化(不能创建对象),专门为其他类提供继承信息。
    • 抽象方法:如果一个方法没有方法体,就可以定义为抽象方法,也是用abstract关键字修饰,如果一个类有抽象方法,这个类必须被声明为抽象类。子类继承该抽象类时必须重写抽象方法。
    • 终结类:被final关键字修饰的类,终结类不能被继承,工具类通常声明为终结类。
    • 终结方法:被final关键字修饰的方法,子类中不能重写终结方法。
    • 静态方法:被static修饰的方法,静态的方法和属性属于类,不属于对象,在内存中只有唯一的拷贝,静态方法和属性调用的方式是用类名调用,而不是通过对象的引用来调用。

练习:创建一个自定义窗口类、一个图形类、一个矩形类、一个椭圆类、一个直线类,编程实现在自定义窗口中画出矩形、椭圆及直线

package cn.libill.ui;import java.awt.Graphics;import javax.swing.JFrame;import cn.libill.util.MyUtil;import cn.liblill.shape.Oval;import cn.liblill.shape.Shape;/** * 自定义窗口 * @author libill * */@SuppressWarnings("serial")public class MyFrame extends JFrame {    private Shape[] shapes = new Shape[100];    public MyFrame() {        this.setTitle("围棋");    //设置窗口标题        this.setSize(800, 600); //设置窗口大小        this.setResizable(false);   //不可调整窗口大小        this.setDefaultCloseOperation(EXIT_ON_CLOSE);   //关闭窗口时退出程序(后台)        this.setLocationRelativeTo(null);   //窗口居中        for (int i = 0; i < shapes.length; i++) {            switch(MyUtil.random(1, 3)) {            case 1: shapes[i] = new Oval(); break;            case 2: shapes[i] = new Oval(); break;            case 3: shapes[i] = new Oval(); break;            }            shapes[i].setX1(MyUtil.random(0, 800));            shapes[i].setY1(MyUtil.random(0, 600));            shapes[i].setX2(MyUtil.random(0, 800));            shapes[i].setY2(MyUtil.random(0, 600));            shapes[i].setColor(MyUtil.createRandomColor()); //设置画笔颜色        }    }    @Override    public void paint(Graphics g) {        super.paint(g);    /*  g.setColor(Color.ORANGE);        g.fillRect(0, 0, 600, 600);        g.setColor(Color.BLACK);        g.drawRect(36, 36, 548, 548);        for (int i = 0; i < 19; i++) {            g.drawLine(40, 40 + 30 * i, 580, 40 + 30 * i);            g.drawLine(40 + 30 * i, 40, 40 + 30 * i, 580);        }        for (int i = 0; i < 3; i++) {            for (int j = 0; j < 3; j++) {                g.fillOval(120 + 180 * i + 5, 120 + 180 * j + 5, 10, 10);            }        }*/        for (Shape s : shapes) {            s.draw(g);        }    }}
package cn.liblill.shape;import java.awt.Color;import java.awt.Graphics;/** * 图形抽象类 * @author libill * */public abstract class Shape {    protected int x1;   //起点横坐标    protected int y1;   //起点纵坐标    protected int x2;   //终点横坐标    protected int y2;   //终点纵坐标    protected Color color; //画笔颜色    /**     * 绘画(抽象方法留给子类实现)     * @param g 画笔     */    public abstract void draw(Graphics g);    /**     * 起点横坐标访问器     * @return 起点横坐标     */    public int getX1() {        return x1;    }    /**     * 起点横坐标修改器     * @param x1 起点横坐标     */    public void setX1(int x1) {        this.x1 = x1;    }    /**     * 起点纵坐标访问器     * @return 起点纵坐标     */    public int getY1() {        return y1;    }    /**     * 起点纵坐标修改器     * @param y1 起点纵坐标     */    public void setY1(int y1) {        this.y1 = y1;    }    /**     * 终点横坐标访问器     * @return 终点横坐标     */    public int getX2() {        return x2;    }    /**     * 终点横坐标修改器     * @param x2 终点横坐标     */    public void setX2(int x2) {        this.x2 = x2;    }    /**     * 终点纵坐标访问器     * @return 终点纵坐标     */    public int getY2() {        return y2;    }    /**     * 终点纵坐标修改器     * @param y2 终点纵坐标     */    public void setY2(int y2) {        this.y2 = y2;    }    /**     * 画笔颜色修改器     * @param color 画笔颜色     */    public void setColor(Color color) {        this.color = color;    }}
package cn.liblill.shape;import java.awt.Graphics;/** * 矩形类 * @author libill * */public class Rectangle extends Shape {    @Override    public void draw(Graphics g) {        int x1 = getX1() < getX2() ? getX1() : getX2();         int y1 = getY1() < getY2() ? getY1() : getY2();         int x2 = getX1() > getX2() ? getX1() : getX2();         int y2 = getY1() > getY2() ? getY1() : getY2();         int width = Math.abs(x2 - x1);        int height = Math.abs(y2 - y1);        g.setColor(color);        g.drawRect(x1, y1, width, height);    }}
package cn.liblill.shape;import java.awt.Graphics;/** * 椭圆类 * @author libill * */public class Oval extends Shape {    @Override    public void draw(Graphics g) {        int x1 = getX1() < getX2() ? getX1() : getX2();         int y1 = getY1() < getY2() ? getY1() : getY2();         int x2 = getX1() > getX2() ? getX1() : getX2();         int y2 = getY1() > getY2() ? getY1() : getY2();         int width = Math.abs(x2 - x1);        int height = Math.abs(y2 - y1);        g.setColor(color);        g.drawOval(x1, y1, width, height);    }}
package cn.liblill.shape;import java.awt.Graphics;/** *  直线类 * @author libill * */public class Line extends Shape {    @Override    public void draw(Graphics g) {        g.setColor(color);        g.drawLine(x1, y1, x2, y2);    }}
package cn.libill.util;import java.awt.Color;/** * 自定义工具类 * @author libill * */public final class MyUtil { //加final表明该类不能被继承,没有任何子类(断子绝孙类)    /**     * 将构构器私有,不能在外部创建MyUtil类,要访问该类中的方法,只能用(MyUtil.)来调用     */    private MyUtil() {    }    /**     * 产生指定范围的随机数     * @param min 最小值 (闭区间)     * @param max 最大值 (闭区间)     * @return 指定范围的随机数     */    public static int random(int min, int max) {        return (int) (Math.random() * (max - min + 1) + min);    }    /**     * 生成随机颜色     * @return Color对象     */    public static Color createRandomColor() {        int r = random(0, 255);        int g = random(0, 255);        int b = random(0, 255);        return new Color(r, g, b);    }}
package cn.libill.test;import cn.libill.ui.MyFrame;/** * 测试类 * @author libill * */public class MyFrameTest {    public static void main(String[] args) {        new MyFrame().setVisible(true);    }}

作业:公司员工有三类,分别是部门经理、程序员、销售员。部门经理每月工资8000元,程序员每小时100元,销售人员底薪1200元,加上当月销售额5%的提成,编程完成工资结算系统)

package cn.libill;/** * 员工类 * @author libill * */public abstract class Employee {    protected String name;  //员工姓名    /**     * 构造器     * @param name 员工姓名     */    public Employee(String name) {        super();        this.name = name;    }    /**     * 工资     */    public abstract double salary();    /**     * 员工姓名访问器     * @return 员工姓名     */    public String getName() {        return name;    }}
package cn.libill;/** * 部门经理类 * @author libill * */public class Manager extends Employee {    /**     * 构造器     * @param name 经理姓名     */    public Manager(String name) {        super(name);    }    @Override    public double salary() {        return 8000;    }}
package cn.libill;/** * 程序员类 * @author libill * */public class Programmer extends Employee {    private double hours;   //工作小时    /**     * 构造器     * @param name 程序员姓名     */    public Programmer(String name) {        super(name);    }    /**     * 设置程序员工作多少小时     * @param hours 工作小时     */    public void setHours(double hours) {        this.hours = hours;    }    @Override    public double salary() {        return 100 * hours;    }}
package cn.libill;/** * 销售员类 * @author libill * */public class SalesMan extends Employee {    private double salesVolume;     //销售额    /**     * 构造器     * @param name 销售员姓名     */    public SalesMan(String name) {        super(name);    }    /**     * 设置销售员销售额      * @param salesVolume 销售额     */    public void setSalesVolume(double salesVolume) {        this.salesVolume = salesVolume;    }    @Override    public double salary() {        return 1200 + salesVolume * 0.05;    }}
package cn.libill;import java.util.Scanner;/** * 工资结算类 * @author libill * */public class WageCalculation {    public static void main(String[] args) {        Scanner sc = new Scanner(System.in);        Employee[] e = new Employee[10];        String[] names = {"张    三", "李    四", "王麻子", "王大锤", "元    芳",                          "刘    阳", "肖继芳", "淑   芳", "陈    明", "李    静"};        for (int i = 0; i < e.length; i++) {            double m =  Math.random();            if (m <= 0.6) {         //60%的员工为销售员                e[i] = new SalesMan(names[i]);            } else if (m <= 0.9) {  //30%的员工为程序员                e[i] = new Programmer(names[i]);            } else {                //10%的员工为部门经理                e[i] = new Manager(names[i]);            }        }        for (int i = 0; i < e.length; i++) {            if (e[i] instanceof Manager) {                System.out.printf("【%s】 职位:经    理,本月工资为:%.2f\n", e[i].getName(), e[i].salary());            } else if (e[i] instanceof Programmer) {                System.out.printf("【%s】 职位:程序员, 请输入工作小时:", e[i].getName());                ((Programmer) e[i]).setHours(sc.nextDouble());                System.out.printf("\t本月工资为:%.2f\n", e[i].salary());            } else {                System.out.printf("【%s】 职位:销售员, 请输入销售额:", e[i].getName());                ((SalesMan) e[i]).setSalesVolume(sc.nextDouble());                System.out.printf("\t本月工资为:%.2f\n", e[i].salary());            }        }        sc.close();    }}

由于部门经理、程序员和销售人员的共有特性都是公司的员工,所以创建一个Employee父类,并且都要计算工资,所以父类中应该具有姓名属性以及工资计算方法,因为在父类中无法实现对每个子类工资的计算,所以将其申明为抽象方法,让各子类去实现工资计算方法。由于父类中有抽象方法,所以父类也必须申明为抽象类。

0 0