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

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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值