14抽象类和接口

抽象类和接口

1.抽象类

1.抽象方法没有方法体,使用abstract关键字修饰,必须存在于抽象类中

2.抽象类不能直接new对象,必须通过new子类的方式类创建对象(也就是多态向上转型的方式)

3.子类必须重写父类的所有抽象方法,除非子类也是抽象类

4.抽象类中可以书写普通属性,普通方法,构造方法,用于给子类使用

5.抽象类依然可以实现多态。实现的方式与之前一致:父类作为形参和父类作为返回值

N.静态方法可以被继承,不能被重写

package com.edu.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.edu.test1;

public class Tiger extends Animal{

	@Override
	public void eat() {
		System.out.println("老虎吃肉");
	}

}

package com.edu.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.edu.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.edu.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.edu.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.edu.test2;

public class CommonDoor extends Door{

	@Override
	public void open() {
		System.out.println("普通门开门,插入钥匙,轻轻滴,一转,门开了");
	}

	@Override
	public void close() {
		System.out.println("普通门关门,啪的一声,门关了");
	}

}

package com.edu.test2;

public class SecurityDoor extends Door{

	@Override
	public void open() {
		System.out.println("防盗门开门:指纹 +  人脸识别 + 密码解锁 ,门开了");
	}

	@Override
	public void close() {
		System.out.println("防盗门关门:自动关门");
	}

}

package com.edu.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.edu.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.edu.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.edu.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.edu.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.edu.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.edu.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.edu.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.edu.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.edu.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.edu.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.edu.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.edu.test7;
/**
 * 	墨盒接口
 * @author WHD
 *
 */
public interface InkBox {
	String getInkBoxType();
}

package com.qfedu.test7;

public class BlackInkBox implements InkBox{

	@Override
	public String getInkBoxType() {
		return "黑色墨盒";
	}

}

package com.edu.test7;

public class ColorInkBox implements InkBox{

	@Override
	public String getInkBoxType() {
		return "彩色墨盒";
	}

}

package com.edu.test7;

public interface Paper {
	String getPaperType();
}

package com.edu.test7;

public class A4 implements Paper{

	@Override
	public String getPaperType() {
		return "A4";
	}

}

package com.edu.test7;

public class B5 implements Paper{

	@Override
	public String getPaperType() {
		return "B5";
	}

}

package com.edu.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. 接口总结

当你关注事物的本质,使用抽象类;当你关注某个功能,使用接口

因为抽象类可以描述属性和行为,而接口只能描述功能

相同点
代表系统的抽象层

​ 都不能被实例化

​ 都能包含抽象方法

​ 用于描述系统提供的服务,不必提供具体实现

不同点
在抽象类中可以为部分方法提供默认实现,而接口中只能包含抽象方法

​ 抽象类便于复用,接口便于代码维护

​ 一个类只能继承一个直接的父类,但可以实现多个接口

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值