2018.4.2
Abstract 修饰抽象类
昨天的问题:
在英雄联盟中,要求所有的英雄都有QWER四个技能,但是没有一个技能一样。
昨天是通过重写的方式完成操作,但是存在隐患,就是没有强制要求子类来重写这个方法,
这样的话就有可能导致在程序开发的工程中,开发者忘记了重写这个方法,而且没有任何的提示,
也不会有任何的编译错误,但是运行时会发现不符合业务逻辑或者生活逻辑的错。
要求继承于该类的子类,【强制】重写这些技能方法,不写就报错,将业务逻辑的问题提升到语法问题,错误前置(编译之后的错误提到编译之前)。
【解决】
abstract 修饰【抽象】类的关键字,
也是修饰抽象方法的关键字。
[注意事项]
1.如果一个方法用abstract修饰,那么这个方法是不能有**方法体**的,这个称之为方法的声明。
一个方法如果用abstract修饰,【那么要求继承该类的子类必须重写这个方法】
2.如果一个类中存在一个用abstract修饰的方法,那么这个类必须用abstract修饰。
3.抽象类不能有自己的类对象
【why】 因为在用abstract修饰的抽象类当中,有可能存在抽象方法,而抽象方法是没有方法体,不知道应该运行什么代码
,而创建抽象类对象之后,就会存在这样的隐患,
所有【抽象类但是没有自己的类对象】。
4.如果一个类用abstract修饰,但是不包含抽象方法是可以的,但是没有意义。
语法没有问题,但是没有实际意义。
【总结】
如果一个类集成了用abstract修饰的抽象类,那么要求该类必须【实现】抽象类中所有方法。
这里要求所有英雄都有三个技能,分别是QWE,而且要求继承该Hero的子类,必须重写这三个方法
这里就可以使用abstract来修饰这些方法。
abstract class Hero {//有abstract方法,必须用abstract修饰类。
//成员变量
int blood;
int power;
public Hero() {}
public Hero(int blood,int power) {
this.blood = blood;
this.power = power;
}
abstract public void Q() ;//没有方法体,叫方法的声明。
abstract public void W() ;//没有方法体,叫方法的声明。
abstract public void E() ;//没有方法体,叫方法的声明。
public void test() {
System.out.println("测试");
}
}
Fizz这个类是继承了Hero类,因为Hero中包含了三个用abstract修饰的方法
那么要求在Fizz类中必须【实现】这三个方法。
class Fizz extends Hero {
//提供一个构造方法Fizz
public Fizz() {}
public Fizz(int blood,int power) {
super(blood,power);//调用父类的构造方法,初始化父类的成员变量。
}
//是实现父类中要求继承该父类的子类必须【实现】的Q方法 implement
@Override
public void Q() {
System.out.println("淘气打击");
}
//是实现父类中要求继承该父类的子类必须【实现】的W方法 implement
@Override
public void W() {
System.out.println("三叉戟");
}
//是实现父类中要求继承该父类的子类必须【实现】的E方法 implement
@Override
public void E() {
System.out.println("古灵精怪");
}
}
public class Demo1 {
public static void main(String[] args) {
Fizz fizz = new Fizz(100,190);
fizz.Q();
fizz.W();
fizz.E();
//Hero hero = new Hero();
}
}
结果:
淘气打击
三叉戟
古灵精怪
抽象类实例应用
[需求] 描述一个图形类 shape类,要求所有继承于该类的子类都要有计算周长和面积的方法
实现shape类
实现继承shape类的 圆类 方块 三角。
abstract class Shape {
abstract public float perimeter();
abstract public float square();
}
class Circle extends Shape {
private float r;
private float pi = 3.1415f;
public Circle() {}
@Override
public float perimeter() {
// TODO Auto-generated method stub
return 2*r*pi;
}
@Override
public float square() {
// TODO Auto-generated method stub
return 0;
}
}
public class Demo2 {
public static void main(String[] args) {
//匿名内部类。
new Shape() {
@Override
public float square() {
// TODO Auto-generated method stub
return 0;
}
@Override
public float perimeter() {
// TODO Auto-generated method stub
return 0;
}
};
}
}
interface 接口
代码中的接口:拓展当前类的功能,或者用来打补丁。
接口用到的关键字
interface UI: User Interface(用户接口 用户界面)
格式:
interface 接口名 {
//扩展的内容
成员变量和成员方法
}
接口名采用的命名法则是大驼峰命名法
【遵从】接口的关键字
implements(实现,遵从)
【发现】
【补充知识】
final 最终的
final关键字可以用来修饰成员变量和局部变量,用final修饰的变量在赋值之后不能发生改变。
final 如果修饰一个类
一个类被final修饰 该类不能被继承
例如:String类
final修饰一个方法呢?
不能被重写。
接口中的成员方法是没有方法体的,默认的
[接口中 的缺省属性]
1.在接口中成员变量默认的【缺省属性】是public static final修饰,要求在定义成员变量时直接复赋值。
例如:就好比USB接口在定义标准的时候就确定了这个usb接口的尺寸。
2.在接口中的成员方法的【缺省属性】是abstract,这里是要求【遵从】接口的类来完成。
例如:usb接口规定了链接的方式和硬件要求。
[注意事项] 1.在interface中定义的方法都是abstract修饰的方法,要求遵从接口的类要实现这些方法。 2.在interface中定义的成员变量都是final修饰的,只有使用权没有赋值权 3.一个类可以【遵从】多个接口。不能继承多个类,java是单继承的。 不同的接口用“,”隔开 、 java是一门单继承,多实现/遵从
interface A {
//成员变量
int num = 10;//【缺省(默认值)属性】public static final;
//成员方法
public void testA();//缺省属性: public abstract
}
interface B {
public void testB();
}
//这里使用implements关键字来遵从接口
public class Demo3 implements A,B {//单继承 多遵从。
@Override
public void testA() {
System.out.println("实现接口中要求完成的testA方法");
}
@Override
public void testB() {
System.out.println("实现接口中要求完成的testB方法");
}
public static void main(String[] args) {
Demo3 d1 = new Demo3();
d1.testA();//【遵从】接口,并且实现接口中规定的方法,调用该方法
d1.testB();
System.out.println(d1.num);//[遵从]接口,使用接口中的成员变量
//d1.num = 200;//不能改变。因为在接口定义的成员变量默认的缺省属性都是public static final
//而final修饰的变量里面的数据是不能发生改变的。
}
}
结果:
实现接口中要求完成的testA方法
实现接口中要求完成的testB方法
10
案例
生活汇总的铅笔,一头是铅笔,一头是橡皮
橡皮看作是一个扩展功能,用【接口】来表示。
interface Eraser {
int length = 8;//【缺省属性】public static final
public void clear();//[缺省属性]abstract
}
class Pencil implements Eraser {
@Override
public void clear() {
System.out.println("这个橡皮是用来啃的");
}
public void write() {
System.out.println("画画");
}
}
public class Demo4 {
public static void main(String[] args) {
Pencil p =new Pencil();
p.clear();
p.write();
}
}
结果:
这个橡皮是用来啃的
画画