抽象类和接口
初识抽象类和抽象方法
区分普通方法和抽象方法
在Java中,当一个类的方法被abstract关键字修饰时,该方法称为抽象方法。抽象方法所在的类必须定义为抽象类。
当一个方法被定义为抽象方法后,意味着该方法不会有具体的实现,而是在抽象类的子类中通过方法重写进行实现。定义抽象方法的语法格式如下:
[访问修饰符]abstract<返回类型><方法名>([参数列表]);
abstract关键字表示该方法被定义为抽象方法。
普通方法和抽象方法相比,主要有下列两点区别:
抽象方法需要需要用修饰符abstract修饰,普通方法不需要。
普通方法有方法体,抽象方法没有方法体。
区分普通类和抽象类
在Java中,当一个类被abstract关键字修饰时,该类称为抽象类。
定义抽象类的语法格式如下:
abstract class<类名>{
}
abstract关键字表示该类被定义为抽象类。
普通类和抽象类相比,主要有下列两点区别:
抽象类需要用修饰符abstract修饰,普通类不需要。
普通类可以实例化,抽象类不能被实例化。
定义一个抽象类
当一个类被定义为抽象类时,它可以包含各种类型的成员,包括属性、方法等,其中方法又可分为普通方法和抽象方法,如下面的抽象类结构示例:
public abstract class 类名称{
修饰符 abstract 返回类型 方法名();
修饰符 返回类型 方法名(){
方法体
}
}
注意:抽象方法只能定义在抽象类中。但是抽象类中可以包含抽象方法,也可以包含普通方法,还可以包含普通类包含的一切成员。
使用抽象类描述抽象的事物
下面通过一个实例简单认识抽象类和抽象方法的用法。
示例一:
public abstract class Man {
private String name;
String sex;
int age;
double height;
double weight;
public abstract void eat();
public abstract void drink();
public void shit(){
System.out.println("Shit!!!!");
}
public void sleep(){
System.out.println("睡就是了!!!! ");
}
protected String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class Student extends Man {
@Override
public void eat() {
}
@Override
public void drink() {
}
@Override
public void sleep() {
super.sleep();
}
}
总结
抽象类abstract关键字修饰类
抽象类不能被实例化(不能创建对象)
抽象方法:
抽象方法必须在抽象类中
抽象方法没有结构体
子类继承抽象类的时候,必须实现父类的抽象方法,除非这个子类也是抽象类
接口
生活中的接口
在现实生活中,USB接口实际上是某些企业和组织制定的一种约定或标准,规定了接口的大小、形状等。按照该约定设计的各种设备,如U盘、USB风扇、USB键盘都可以插到USB接口上正常工作。USB接口相关工作是按照如下步骤进行的。
(1)约定USB接口标准。
(2)制作符合USB接口约定的各种具体设备。
(3)把USB设备插到USB接口上进行工作。
Java中接口的作用和生活中的接口类似,它提供一种约定,使得实现接口的类(或结构)在形式上保持一致。
如果抽象类中所有的方法都是抽象方法,就可以使用Java提供的接口来表示。从这个角度来讲,接口可以看作是一种特殊的“抽象类”,但是采用与抽象类完全不同的语法来表示,两者的设计理念也不同。
定义和实现一个简单的接口
简单来说,接口是一个不能实例化的类型。接口类型的定义类似于类的定义,语法格式如下:
public interface 接口名{
//接口成员
}
和抽象类不同,定义接口使用interface修饰符,访问修饰符只能是public,且可选。
接口成员可以是全局变量和公共的抽象的方法。
与抽象类一样,使用接口也必须通过子类,子类通过implements关键字实现接口。
实现接口的语法格式如下:
public 类名 implements 接口名{
实现方法
普通方法
}
实现接口使用implements关键字。
实现接口必须实现接口中定义的所有抽象方法。接口的实现类允许包含普通方法。
示例二:
实现USB接口。
public interface USB {
public static final int LENGTH=10;//长度
int WIDTh = 3;//宽度
double POWER=1.5;
// void power();
void connect();
}
public class USBMouse implements USB {
@Override
public void connect() {
System.out.println("点击鼠标,啪啪啪,LOL玩起来");
}
}
public class USBFlash implements USB{
@Override
public void connect() {
System.out.println("500G的种子请拿走!");
}
}
public class Computer {
public void control(USB usbDevice){
usbDevice.connect();
}
public static void main(String[] args) {
Computer c=new Computer();
USBMouse m=new USBMouse();
USBFlash f=new USBFlash();
c.control(m);
c.control(f);
}
}
输出结果:
更复杂的接口
接口本身也可以继承接口。
接口继承的语法格式如下:
[修饰符]interface 接口名 extends 父接口1,父接口2…{
常量接口
方法定义
}
一个普通类只能继承一个父类,但能同时实现多个接口,也可以同时继承抽象类和实现接口。
实现多个接口的语法格式如下:
class 类名 extends 父类名 implements 接口1,接口2,…{
类的成员
}
关于定义和实现接口,需要注意以下几个方面的内容。
接口和类、抽象类是一个层次的概念,命名规则相同。
修饰符如果是public,则该接口在整个项目中可见。如果省略修饰符,该接口只在当前包中可见。
接口中可以定义常量,不能定义变量。接口中的属性都默认用“public static final”修饰,即接口中的属性都是全局静态常量。接口中的常量必须在定义时指定初始值,举例如下:
public static final int PI=3.14;
int PI-3.14;//在接口中,这两个定义语句的效果完全相同
int PI; //错误,在接口中定义时必须指定初始值,如果在类中定义会有默认值
接口中的所有方法都是抽象方法,接口中的方法都默认为public。
和抽象类一样,接口同样不能实例化,接口中不能有构造方法。
接口间可以通过extends实现继承关系,一个接口可以继承多个接口,但接口不能继承类。
类只能继承一个父类,但可以通过implements实现多个接口。一个类必须实现接口的全部方法,否则必须定义为抽象。若一个类在继承父类的同时又实现了多个接口,extends必须位于implements之前。
示例三:
门有“开”和“关”的功能,锁有“上锁”和“开锁”的功能
将门定义为抽象类,锁定义为接口。
防盗门继承门,实现锁的接口。
public abstract class Door {
public abstract void open();
public abstract void close();
}
public interface Lock {//interface关键字声明接口
//接口中所有的方法都是公共抽象方法
public abstract void lockUp();
void lockDown();
}
public interface Camera {
void takePhoto();
}
public class DefenderDoor extends Door implements Lock,Camera{
@Override
public void open() {
System.out.println("门开了!");
takePhoto();
}
@Override
public void close() {
System.out.println("门关了!");
takePhoto();
}
@Override
public void lockUp() {
System.out.println("锁开了!");
}
@Override
public void lockDown() {
System.out.println("锁上了!");
}
@Override
public void takePhoto() {
System.out.println("拍照");
}
}
public class Master {
String name;
DefenderDoor door;
public void getIn(){
System.out.println(name+"掏出一串钥匙,插入锁孔开始转动");
door.lockUp();
door.open();
System.out.println("进入房间!");
}
public void getOut(){
System.out.println("走出房间");
door.close();
System.out.println("掏出一串钥匙,插入锁孔,开始转动");
door.lockDown();
}
}
public class TestMaster {
public static void main(String[] args) {
Master m=new Master();
m.name="包租婆";
m.door=new DefenderDoor();
m.getIn();
m.getOut();
}
}
输出结果:
示例四:
原始的手机,可以发短信,通电话。随着发展,手机增加了功能:音频、视频播放、拍照、上网。使用接口实现手机功能。
public abstract class Handset {
public abstract void sengInfo();
public abstract void call();
public abstract void info();
}
public interface TheakePictures {
void takePictures();
}
public interface Network {
void networkConn();
}
public interface PlayWiring {
void play(String content);
}
public class Phone {
String pinpai;
String xinhao;
public Phone(String xinhao, String pinpai) {
this.xinhao=xinhao;
this.pinpai=pinpai;
System.out.println("这是一款型号为:"+this.xinhao+",品牌是:"+this.pinpai+"的手机!");
}
public class CommonHandset extends Handset implements PlayWiring ,Network,TheakePictures{
@Override
public void sengInfo() {
System.out.println("发信息。。。");
}
@Override
public void call() {
System.out.println("打电话。。。");
}
@Override
public void info() {
System.out.println("接收信息。。。");
}
@Override
public void play(String content) {
System.out.println("播放"+content);
}
@Override
public void networkConn() {
System.out.println("已经启动移动网络。。。");
}
@Override
public void takePictures() {
System.out.println("咔嚓。。。拍照成功。。");
}
}
public class TextCommon {
public static void main(String[] args) {
Phone phone1 = new Phone("G502c ", "索尼爱立信 ");
CommonHandset c=new CommonHandset();
c.sengInfo();
c.info();
c.play("《热血》");
Phone phone2=new Phone("HTC","I9100");
c.networkConn();
c.play("《小时代》");
c.takePictures();
c.sengInfo();
c.call();
}
}
输出结果:
示例五:
开发打印机
墨盒:彩色、黑白
纸张类型:A4、B5
墨盒和纸张都不是打印机厂商提供的
打印机厂商要兼容市场上的墨盒、纸张
public interface Paper {
String getSize();
}
public interface InkBox {
String getcolcor();
}
public class A4Paper implements Paper {
@Override
public String getSize() {
return "A4";
}
}
public class B5Paper implements Paper {
@Override
public String getSize() {
return "B5";
}
}
public class BlackInkBox implements InkBox {
@Override
public String getcolcor() {
return "黑色";
}
}
public class ColorfulInkBox implements InkBox {
@Override
public String getcolcor() {
return "彩色";
}
}
public class PaperAndInkBox extends Paper {
}
public class Printer {
public void print(Paper p,InkBox box){
System.out.println("使用" + box.getcolcor()+ "墨盒在" +p.getSize()+"纸上打印");
}
public static void main(String[] args) {
Printer p=new Printer();
Paper paper = new A4Paper();
InkBox box = new ColorfulInkBox();
p.print(paper, box);
}
}
输出结果:
示例六:组装一台计算机
需求说明:
采用面向接口编程思想组装一台计算机
计算机的主要组成部分
CPU
硬盘
内存
实现思路:
定义CPU的接口CPU,返回CPU品牌和主频
定义内存的接口EMS,返回类型和容量
定义硬盘的接口HardDisk,返回容量
编写各组件厂商分别实现CPU、EMS、和HardDisk接口
编写计算机类,组装计算机并显示相关信息
编写测试类运行
public interface CPU {
void cpu();
void zhupin();
}
public interface EMS {
void leixing();
void rongliang();
}
public interface HardDisk {
void yingpan();
}
public class ChanShang implements CPU,EMS, HardDisk {
@Override
public void cpu() {
}
@Override
public void zhupin() {
}
@Override
public void leixing() {
}
@Override
public void rongliang() {
}
@Override
public void yingpan(){
}
}
public class computer {
String pingpai;
String zhupin;
String leixing;
int ronglianng;
int liang;
public computer(String pingpai,String zhupin,int rongliang ,int liang){
this.pingpai=pingpai;
this.zhupin=zhupin;
this.ronglianng=rongliang;
this.liang=liang;
System.out.println("Cpu品牌是:" + pingpai +
",主频是:" + zhupin+",硬盘容量是:"+rongliang+",内存容量:"+liang );
}
public class TestComputer {
public static void main(String[] args) {
System.out.println("这个电脑的信息是:");
computer c=new computer("Intel","3.8GHz",3000,4);
}
}
输出结果:
接口的使用
接口中的成员变量:
默认都是public static final的,必须显式初始化。
接口中的方法:
默认都是public abstract的。
接口没有构造方法,不能被实例化。
一个接口不能实现另一个接口,但可以继承多个其他接口。
一个类必须实现接口抽象方法(implements),除非这个类也是抽象类。
抽象类vs接口
相同点:
代表系统的抽象层。
都不能被实例化。
都能包含抽象方法。
用于描述系统提供的服务,不必提供具体实现。
不同点:
在抽象类中可以为部分方法提供默认实现,而接口中只能包含抽象方法。
抽象类便于复用,接口便于代码维护。
一个类只能继承一个直接的父类,但可以实现多个接口。
使用原则:
接口做系统与外界交互的窗口。
接口提供服务。
接口本身一旦制定,就不允许随意修改。
抽象类可完成部分功能实现,还有部分功能可作为系统的扩展点。
面向对象设计原则:
多用组合,少用继承。
针对接口编程。
针对扩展开放,针对改变关闭。
总结
Java中的接口:
属性全都是全局静态常量。
方法都是全局抽象方法。
无构造方法。
一个类可以实现多个接口,非抽象类实现接口时必须实现接口中的全部方法。
抽象类利于代码复用,接口利于代码维护。