1.抽象类
1.抽象方法没有方法体,使用abstract关键字修饰,必须存在于抽象类中
2.抽象类不能直接new对象,必须通过new子类的方式类创建对象(也就是多态向上转型的方式)
3.子类必须重写父类的所有抽象方法,除非子类也是抽象类
4.抽象类中可以书写普通属性,普通方法,构造方法,用于给子类使用
5.抽象类依然可以实现多态。实现的方式与之前一致:父类作为形参和父类作为返回值
N.静态方法可以被继承,不能被重写
package com.qfedu.test1;
/**
* 抽象类
* abstract-抽象:模糊,不具体的
*
* 类是对象的抽象,对象是类的具体,万物皆对象
*
* 类的组成部分:属性 和 方法
* @author WHD
*
*/
public abstract class Animal {
private String animalType;
public String getAnimalType() {
return animalType;
}
public void setAnimalType(String animalType) {
this.animalType = animalType;
}
public Animal() {}
public Animal(String animalType) {
this.animalType = animalType;
}
/**
* 1.抽象方法没有方法体,使用abstract关键字修饰,必须存在于抽象类中
* 2.抽象类不能直接new对象,必须通过new子类的方式类创建对象(也就是多态向上转型的方式)
* 3.子类必须重写父类的抽象方法,除非子类也是抽象类
* 4.抽象类中可以书写普通属性,普通方法,构造方法,用于给子类使用
* 5.抽象类依然可以实现多态。实现的方式与之前一致:父类作为形参和父类作为返回值
* N.静态方法可以被继承,不能被重写
*/
public abstract void eat();
}
package com.qfedu.test1;
public class Tiger extends Animal{
@Override
public void eat() {
System.out.println("老虎吃肉");
}
}
package com.qfedu.test1;
public abstract class Pet extends Animal{
private String lovelyName;
public String getLovelyName() {
return lovelyName;
}
public void setLovelyName(String lovelyName) {
this.lovelyName = lovelyName;
}
public Pet() {
}
public Pet(String animalType,String lovelyName) {
super(animalType);
this.lovelyName = lovelyName;
}
public abstract void play();
}
package com.qfedu.test1;
public class Dog extends Pet{
private String strain;
public String getStrain() {
return strain;
}
public void setStrain(String strain) {
this.strain = strain;
}
public Dog(String strain,String animalType,String lovelyName) {
super(animalType, lovelyName);
this.strain = strain;
}
public Dog() {
}
@Override
public void play() {
System.out.println("狗狗和主人玩耍玩飞盘");
}
@Override
public void eat() {
System.out.println("狗吃骨头");
}
}
package com.qfedu.test1;
public class TestAnimal {
public static void main(String[] args) {
// Animal animal = new Animal(); 不能new对象
Animal tiger = new Tiger(); // 向上转型 可以访问继承父类的方法 和 重写父类的方法
tiger.eat();
System.out.println("-----------------------------");
Animal dog1 = new Dog();
dog1.eat();
System.out.println("-----------------------------");
Pet dog2 = new Dog();
dog2.eat();
dog2.play();
}
}
2. 抽象类案例
package com.qfedu.test2;
/**
* 门
* 父类:门的分类又分为普通门,防盗门
*
* 属性
* 方法
* @author WHD
*
*/
public abstract class Door {
private String brand;
private double price;
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public abstract void open();
public abstract void close();
}
package com.qfedu.test2;
public class CommonDoor extends Door{
@Override
public void open() {
System.out.println("普通门开门,插入钥匙,轻轻滴,一转,门开了");
}
@Override
public void close() {
System.out.println("普通门关门,啪的一声,门关了");
}
}
package com.qfedu.test2;
public class SecurityDoor extends Door{
@Override
public void open() {
System.out.println("防盗门开门:指纹 + 人脸识别 + 密码解锁 ,门开了");
}
@Override
public void close() {
System.out.println("防盗门关门:自动关门");
}
}
package com.qfedu.test2;
public class Person {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void openCommonDoor(CommonDoor cd) {
cd.open();
}
public void openSecurityDoor(SecurityDoor sd) {
sd.open();
}
public void closeCommonDoor(CommonDoor cd) {
cd.close();
}
public void closeSecurityDoor(SecurityDoor sd) {
sd.close();
}
// 以上方法可以使用多态替代 提高程序的扩展性 灵活性
public void openDoor(Door door) {
door.open();
}
public void closeDoor(Door door) {
door.close();
}
public CommonDoor buyCommonDoor() {
return null;
}
public SecurityDoor buySecurityDoor() {
return null;
}
public Door buyDoor(double money) {
if(money >= 5000) {
return new SecurityDoor();
}else {
return new CommonDoor();
}
}
}
package com.qfedu.test2;
public class TestDoor {
public static void main(String[] args) {
Door commonDoor = new CommonDoor();
commonDoor.setBrand("金刚牌");
commonDoor.setPrice(2000);
Person zhaosi = new Person();
zhaosi.openDoor(commonDoor);
zhaosi.closeDoor(commonDoor);
Door securityDoor = new SecurityDoor();
securityDoor.setBrand("大猩猩");
securityDoor.setPrice(5000);
zhaosi.openDoor(securityDoor);
zhaosi.closeDoor(securityDoor);
zhaosi.buyDoor(5500).open();
}
}
3.final关键字
3.1 修饰属性
final:最终
适用场景,可以用来修饰:
属性:
被final修饰的属性,称之为常量,常量要求全部大写,多个单词之间使用下划线分割
常量只能被赋值一次,常量通常(99%)在定义的时候赋值,或者在构造方法中赋值
这两种方式都是为了保证 在使用常量之前 是有值的
package com.qfedu.test3;
/**
* 计算器类
* 此类提供用于计算圆相关的数据
*
* final修饰属性:
* 被final修饰的属性,称之为常量,常量要求全部大写,多个单词之间使用下划线分割
*
* 常量只能被赋值一次,常量通常(99%)在定义的时候赋值,或者在构造方法中赋值
* 这两种方式都是为了保证 在使用常量之前 是有值的
* @author WHD
*
*/
public class TestCalc {
final double PI = 3.14;
int a;
final String COUNTRY_NAME = "中华人民共和国";
final int STUDENT_COUNT;
public TestCalc() {
STUDENT_COUNT = 65;
}
public TestCalc(int a) {
STUDENT_COUNT = 70;
}
public static void main(String[] args) {
TestCalc tc = new TestCalc();
// tc.PI = 3.14;
// tc.pi = 3.24;
System.out.println(tc.PI * 2 * 2);
TestCalc tc1 = new TestCalc();
}
}
PI作为一个常量 其值固定 不能改变 我们经过分析 发现 这个值也没有必要存在多份
所以我们可以再加上static关键字修饰
常量只能被赋值一次,常量通常(99%)在定义的时候赋值,或者在静态代码块中赋值
package com.qfedu.test3;
/**
* 计算器类
* 此类提供用于计算圆相关的数据
*
*
* PI作为一个常量 其值固定 不能改变 我们经过分析 发现 这个值也没有必要存在多份
* 所以我们可以再加上static关键字修饰
*
* 常量只能被赋值一次,常量通常(99%)在定义的时候赋值,或者在静态代码块中赋值
*
*
* @author WHD
*
*/
public class TestCalc1 {
public static final double PI = 3.14;
static final int A;
static {
A = 20;
}
// public TestCalc1() {
// A = 20;
// }
public static void main(String[] args) {
TestCalc1 tc = new TestCalc1();
System.out.println(tc.PI);
System.out.println(TestCalc1.PI);
}
}
3.2 修饰方法
被final修饰的方法不能被重写
package com.qfedu.test3;
/**
* final修饰方法:被final修饰的方法不能被重写
* @author WHD
*
*/
public class TestMethod {
public void m1() {
System.out.println("m1方法");
}
public final void m2() {
System.out.println("m2方法");
}
public static void main(String[] args) {
B b = new B();
b.m1();
b.m2();
}
}
class B extends TestMethod{
public void m1() {
System.out.println("m1方法");
}
// public void m2() {
// System.out.println("m2方法");
// }
}
3.3 修饰类
被final修饰的类不能被继承
package com.qfedu.test3;
/**
* final修饰类:被final修饰的类不能被继承
* @author WHD
*
*/
public final class TestClass {
}
//class C extends TestClass{
//
//}
4. 接口
1.接口中的方法默认都是全局抽象方法 写不写都有public abstract修饰
2.接口不能直接new对象,必须通过new实现类(子类)的方式来创建(多态向上转型)
3.实现类(子类)必须重写接口中的所有抽象方法,除非子类也是抽象类或者接口
4.接口中不能写普通属性(默认都是全局静态常量)、普通方法、构造方法
5.接口可以继承多个接口
6.实现类可以实现多个接口
7.接口依然可以实现多态,实现方式与之前一致:接口(父类)作为形参和返回值
package com.qfedu.test6;
/**
* 手机类 父类
* @author WHD
*
*/
public abstract class Phone {
private String brand;
private String type;
private double price;
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public abstract void sendMessage(String message);
public abstract void call();
}
package com.qfedu.test6;
/**
* 普通手机类
* 普通手机具备较少的功能 所以我们可以让 当前普通手机类 实现较少的接口
* 目前普通具备三个额外的功能 联网 打游戏 听音乐
* @author WHD
*
*/
public class CommonPhone extends Phone implements NetWork,Game,Audio{
@Override
public void sendMessage(String message) {
System.out.println("普通手机发短信,按键打字:" + message);
}
@Override
public void call() {
System.out.println("普通手机按键拨号打电话……");
}
@Override
public void playAudio(String audioName) {
System.out.println("普通手机 听音乐,音质感人:" + audioName);
}
@Override
public void playGame(String gameName) {
System.out.println("普通手机打游戏,画质感人:" + gameName);
}
@Override
public void connect() {
System.out.println("普通手机连接网络2G,网速感人");
}
}
package com.qfedu.test6;
/**
* 智能手机类
* 当一个类 即需要继承 又需要实现接口 先继承 后实现
*/
public class SmartPhone extends Phone implements Audio,Video,Photo,NetWork,Game{
@Override
public void sendMessage(String message) {
System.out.println("智能手机发短信,手写输入:" + message);
}
@Override
public void call() {
System.out.println("智能手机打电话,语音拨号");
}
@Override
public void playGame(String gameName) {
System.out.println("智能手机打游戏,很爽:" + gameName);
}
@Override
public void connect() {
System.out.println("智能手机连接5G网络,网上冲浪");
}
@Override
public void takePhoto() {
System.out.println("智能手机拍照,咔嚓一下,记录美好,记录你我");
}
@Override
public void playVideo(String videoName) {
System.out.println("智能手机播放视频,高清无码:" + videoName);
}
@Override
public void playAudio(String audioName) {
System.out.println("智能手机播放音频,身临其境:" + audioName);
}
}
package com.qfedu.test6;
public interface Audio {
void playAudio(String audioName);
}
package com.qfedu.test6;
public interface Game {
void playGame(String gameName);
}
package com.qfedu.test6;
public interface NetWork {
void connect();
}
package com.qfedu.test6;
public interface Photo {
void takePhoto();
}
package com.qfedu.test6;
public interface Video {
void playVideo(String videoName);
}
package com.qfedu.test6;
public class TestPhone {
public static void main(String[] args) {
CommonPhone nokia = new CommonPhone();
nokia.setBrand("诺基亚");
nokia.setType("5600");
nokia.setPrice(1500);
nokia.connect();
nokia.sendMessage("睡了吗?");
nokia.call();
nokia.playAudio("《发如雪》");
nokia.playGame("《贪吃蛇》");
System.out.println("------------------------------");
SmartPhone huawei = new SmartPhone();
huawei.setBrand("华为");
huawei.setType("p40");
huawei.setPrice(4600);
huawei.sendMessage("真的睡了吗?");
huawei.call();
huawei.connect();
huawei.takePhoto();
huawei.playAudio("《那一夜》");
huawei.playVideo("《色即是空》");
huawei.playGame("《王者荣耀》");
}
}
5.接口实现多态
package com.qfedu.test7;
/**
* 打印机类
* 打印机包含
* 墨盒
* 纸张
* @author WHD
*
*/
public class Printer {
private InkBox inkBox;
private Paper paper;
public void setInkBox(InkBox inkBox) {
this.inkBox = inkBox;
}
public InkBox getInkBox() {
return inkBox;
}
public void setPaper(Paper paper) {
this.paper = paper;
}
public Paper getPaper() {
return paper;
}
public void print() {
System.out.println("使用" + this.getInkBox().getInkBoxType() +"墨盒在"+ this.getPaper().getPaperType() +"纸张上打印");
}
}
package com.qfedu.test7;
/**
* 墨盒接口
* @author WHD
*
*/
public interface InkBox {
String getInkBoxType();
}
package com.qfedu.test7;
public class BlackInkBox implements InkBox{
@Override
public String getInkBoxType() {
return "黑色墨盒";
}
}
package com.qfedu.test7;
public class ColorInkBox implements InkBox{
@Override
public String getInkBoxType() {
return "彩色墨盒";
}
}
package com.qfedu.test7;
public interface Paper {
String getPaperType();
}
package com.qfedu.test7;
public class A4 implements Paper{
@Override
public String getPaperType() {
return "A4";
}
}
package com.qfedu.test7;
public class B5 implements Paper{
@Override
public String getPaperType() {
return "B5";
}
}
package com.qfedu.test7;
/**
* 当你关注事物的本质,使用抽象类
* 当你关注某个功能,使用接口
* @author WHD
*
*/
public class Test {
public static void main(String[] args) {
Printer hp = new Printer();
InkBox colorInkBox = new ColorInkBox();
Paper a4 = new A4();
InkBox blackInkBox = new BlackInkBox();
Paper b5 = new B5();
hp.setInkBox(colorInkBox);
hp.setPaper(a4);
hp.setInkBox(blackInkBox);
hp.setPaper(b5);
hp.print();
}
}
6. 接口总结
当你关注事物的本质,使用抽象类;当你关注某个功能,使用接口
因为抽象类可以描述属性和行为,而接口只能描述功能
相同点 代表系统的抽象层
都不能被实例化
都能包含抽象方法
用于描述系统提供的服务,不必提供具体实现
不同点 在抽象类中可以为部分方法提供默认实现,而接口中只能包含抽象方法
抽象类便于复用,接口便于代码维护
一个类只能继承一个直接的父类,但可以实现多个接口