抽象类和抽象方法的使用
抽象类和抽象方法的使用
package com.atguigu.java;
/*
* abstract关键字的使用
* 1.abstract:抽象的
* 2.abstract可以用来修饰的结构:类、方法
*
* 3. abstract修饰类:即称为抽象类
* > 此类(抽象类)不能实例化
* > 抽象类中一定有构造器,便于子类实例化时调用(涉及:子类对象实例化的全过程)
* > 开发中,都会提供抽象类的子类,让子类对象实例化,完成相关的操作
*
*
* 4. abstract修饰方法:即称为抽象方法
* > 抽象方法只有方法的声明,没有方法体
* > 包含抽象方法的类,一定是一个抽象类。反之,抽象类中可以没有抽象方法的。
* > 若子类重写了父类中的所有的抽象方法后,此子类方可实例化
* 若子类没有重写父类中的所有的抽象方法,则此子类也是一个抽象类,需要使用abstract修饰
*/
public class AbstractTest {
public static void main(String[] args) {
//一旦Person类抽象了,就不可实例化
// Person p1 = new Person();
// p1.eat();
}
}
abstract class Creature{
public abstract void breath();
//breath()是一个抽象方法,之后继承这个 Creature类的的非抽象类要重写这个方法
}
abstract class Person extends Creature{
String name;
int age;
//构造器方法
public Person(){
}
//构造器方法
public Person(String name,int age){
this.name = name;
this.age = age;
}
//方法体内为空 不是抽象方法:
// public void eat(){
//
// }
//抽象方法(只有方法的声明,没有方法体)
//如果一个类里有抽象方法,那么它所在的类就不能造对象,就是抽象类。
//反之,抽象类中可以没有抽象方法。
public abstract void eat();
public void walk(){
System.out.println("人走路");
}
}
class Student extends Person{
public Student(String name,int age){
super(name,age);
}
public Student(){
}
//> 若子类重写了父类中的所有的抽象方法后,此子类方可实例化
//若子类没有重写父类中的所有的抽象方法,则此子类也是一个抽象类,需要使用abstract修饰
// public abstract void eat();是个抽象类,如果没有把这个类重写,或者它所在的类定义成抽象类,那将出错
public void eat(){
System.out.println("学生多吃有营养的食物");
}
//Student extends Person,类Student继承的类Person,由于子类Student没有定义为抽象类,所以要重写父类抽象类Person的breath()方法
public void breath() {
System.out.println("学生应该呼吸新鲜的没有雾霾的空气");
}
}
抽象的应用场景举例
子类不同图形不同面积,父类很难定义一个好的面积函数findArea()的方法体,可以定义为抽象方法,子类在重写。
abstract使用中的注意点
/*
* abstract使用上的注意点:
* 1.abstract不能用来修饰:属性、构造器(构造器只能重载不能重写)等结构
*
* 2.abstract不能用来修饰私有方法(私有方法就不能重写了)、
* 静态方法(如果子父类中都用static修饰某同名同参的方法,那么子类的同名同参的方法不能算是父类的重写)、
* final的方法、final的类(final就是最终了,不让重写,abstract就是让重写,矛盾!)
*
*/
抽象类的练习:基本操作
Employee.java 抽象类
/*
* 编写一个Employee类,声明为抽象类,
包含如下三个属性:name,id,salary。
提供必要的构造器和抽象方法:work()。
*
*
*/
public abstract class Employee {
private String name;
private int id;
private double salary;
public Employee() {
super();
}
public Employee(String name, int id, double salary) {
super();
this.name = name;
this.id = id;
this.salary = salary;
}
public abstract void work();
}
Manager.java领导类
/*
* 对于Manager类来说,他既是员工,还具有奖金(bonus)的属性。
*/
public class Manager extends Employee{
private double bonus;//奖金
public Manager(double bonus) {
super();
this.bonus = bonus;
}
public Manager(String name, int id, double salary, double bonus) {
super(name, id, salary);
this.bonus = bonus;
}
@Override
public void work() {
System.out.println("管理员工,提供公司运行的效率");
}
}
CommonEmployee.java员工类
public class CommonEmployee extends Employee {
@Override
public void work() {
System.out.println("员工在一线车间生产产品");
}
}
EmployeeTest.java测试类
/*
* 请使用继承的思想,设计CommonEmployee类和Manager类,要求类中提供必要的方法进行属性访问。
*/
public class EmployeeTest {
public static void main(String[] args) {
//↓多态
Employee manager = new Manager("库克", 1001, 5000, 50000);
manager.work();
CommonEmployee commonEmployee = new CommonEmployee();
commonEmployee.work();
}
}
结果:
java怎么在类中调用自己方法
类里的方法有带static的和不带的,带static的是类方法,不带的是成员方法。
成员方法要通过这个类的一个实例对象来调用。
在静态方法中可以直接调用本类的其他静态方法(就是方法有声明为static的),非静态方法则可以直接调
用非静态方法或者静态方法,静态方法如果要调用非静态方法需要先创建类对象,通过对象去调用类的非静态方法,
如你有一个方法为public static void xx(){},另一个为public void yy(){},
那么你在xx方法中要调用yy方法则必须要先创建这个类的对象,用对象调用yy方法,
但是如果你想在yy方法中调用xx方法,则可以直接调用xx();即可。
创建抽象类的匿名子类对象
package com.atguigu.java;
/*
* 抽象类的匿名子类
*
*/
public class PersonTest {
public static void main(String[] args) {
//method()是静态方法,main()方法也是个静态方法,所以这能直接调用method() 这个静态方法。
method(new Student());//匿名对象
Worker worker = new Worker();
method1(worker);//非匿名的类Worker,非匿名的对象worker
method1(new Worker());//非匿名的类Worker,匿名的对象
System.out.println("********************");
//创建了一匿名子类的对象,对象名是p,
// 类名不知道,类名不是Person
//Person是抽象类,抽象类不能重写,但是下面这个类重写了,
// 重写了eat()和breath()方法,又没起新类名,只是知道从Person类继承下来的,所以叫匿名子类,
//但其创造的匿名子类的对象名是有的,在此题中,匿名子类的对象名是p。
Person p = new Person(){
@Override//重写
public void eat() {
System.out.println("吃东西");
}
@Override
public void breath() {
System.out.println("好好呼吸");
}
};
method1(p);
//输出↓
// 吃东西
// 好好呼吸
System.out.println("********************");
//创建匿名子类 的 匿名对象↓
method1(new Person(){
@Override
public void eat() {
System.out.println("吃好吃东西");
}
@Override
public void breath() {
System.out.println("好好呼吸新鲜空气");
}
});
}//输出↓
//好好吃东西
//好好呼吸新鲜空气
public static void method1(Person p){
p.eat();
p.breath();
}
public static void method(Student s){
}
}
class Worker extends Person{
@Override
public void eat() {
}
@Override
public void breath() {
}
}
模板方法的设计模式及应用场景
/*
* 抽象类的应用:模板方法的设计模式
*
*/
public class TemplateTest {
public static void main(String[] args) {
SubTemplate t = new SubTemplate();
//子类重写父类的方法了,调用的是子类重写的方法
t.spendTime();
}
}
abstract class Template{
//计算某段代码执行所需要花费的时间
public void spendTime(){
//currentTimeMillis()获得从1970年到执行时所在的时间
long start = System.currentTimeMillis();
this.code();//不确定的部分、易变的部分
long end = System.currentTimeMillis();
System.out.println("花费的时间为:" + (end - start));
}
public abstract void code();
}
// 有些功能是非常确定的,都写好了,里面只是有部分代码是不确定的,
//这里面是花费时间(Template类的code()),把这些不确定的部分抽象一下,再把抽象的方法重写一下,
// 造对象时还是造子类对象,然后还是调固定的方法spendTime(),方法里用的抽象的,易变的部分时code(),
// 就替换为你已经重写好的那个(SubTemplate类中的那个code()) ,这就是一种非常好的设计模式。
class SubTemplate extends Template{
@Override//重写函数为1000以内的质数。
public void code() {
for(int i = 2;i <= 1000;i++){
boolean isFlag = true;
for(int j = 2;j <= Math.sqrt(i);j++){
if(i % j == 0){
isFlag = false;
break;
}
}
if(isFlag){
System.out.println(i);
}
}
}
}
一个练习举例
钩子方法
//抽象类的应用:模板方法的设计模式
public class TemplateMethodTest {
public static void main(String[] args) {
BankTemplateMethod btm = new DrawMoney();
btm.process();
BankTemplateMethod btm2 = new ManageMoney();
btm2.process();
}
}
abstract class BankTemplateMethod {
// 具体方法
public void takeNumber() {
System.out.println("取号排队");
}
public abstract void transact(); // 办理具体的业务 //钩子方法
public void evaluate() {
System.out.println("反馈评分");
}
// 模板方法,把基本操作组合到一起,子类一般不能重写
public final void process() {
this.takeNumber();
this.transact();// 像个钩子,具体执行时,挂哪个子类,就执行哪个子类的实现代码
this.evaluate();
}
}
//不同的人办的业务不一样,给public abstract void transact();抽象化了,
// 把取款的和理财的对应的业务的功能在子类里重写上,重写上后就算是完成了,
// 就能在测试类中new子类的对象,这样去调public void transact()。
class DrawMoney extends BankTemplateMethod {
public void transact() {
System.out.println("我要取款!!!");
}
}
class ManageMoney extends BankTemplateMethod {
public void transact() {
System.out.println("我要理财!我这里有2000万美元!!");
}
}