抽象类:包含一个抽象方法的类称为抽象类。抽象方法是只声明而未实现的方法;
所有的抽象方法必须使用abstract关键字声明,所有的抽象类也必须使用abstract关键字声明
例如:
abstract class A1{ public abstract void fun(); }
抽象方法的特点:
1、不能直接进行实例化的操作,但是可以声明,如果想使用抽象类则必须依靠子类。
2、抽象类必须被子类继承,并且被继承的的子类需要实现抽象类中的全部抽象方法。
3、不能使用final声明
4、抽象类中允许有构造方法,但是此构造方法是不能直接被调用的,是交给子类去调用的,子类对象实例化过程,永远是先调用父类中的构造方法。
5、抽象类中的属性如果想要初始化,则肯定还是依赖构造方法
public class AbstractDemo { public static void main(String args[]) { B1 b1 = new B1(); b1.fun(); } } abstract class A1 { public abstract void fun(); } class B1 extends A1 { @Override public void fun() { // TODO Auto-generated method stub System.out.println("....b1...."); } } //结果: //....b1....
抽象类的应用:
从对象多态性的概念上来看,子类为父类实例化是一个比较容易的操作,因为可以发生自动的向上转型关系,那么调用方法永远是呗子类覆写过的方法。
那么,此时可以利用此概念通过对象多态性为抽象类实例化
abstract class AbstractDemoA{ public abstract void fun1(); } class AbstractDemoB extends AbstractDemoA{ public void fun1(){ System.out.println("———abstractDemoB—————"); } } public class AbstractDemo1 { public static void main(String args[]){ AbstractDemoA abstractDemoA = new AbstractDemoB(); abstractDemoA.fun1(); } } //结果: //———abstractDemoB—————
例子:
例如:人分为两种:工人和学生
*假设工人和学生都有姓名和年龄属性,但是工人有工资,学生有成绩
*工人和学生都可以说话,但是说话的内容不一样
package com.demo; abstract class Person { private String name; private String age; public Person(String name, String age) { super(); this.name = name; this.age = age; } public void say(){ sayContent(); } public abstract void sayContent(); public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAge() { return age; } public void setAge(String age) { this.age = age; } } class Student extends Person{ private float score; public Student(String name, String age,float score) { super(name, age); this.score = score; // TODO Auto-generated constructor stub } @Override public void sayContent() { // TODO Auto-generated method stub System.out.println("I'm a student"+" socre="+score); } } class Worker extends Person{ public Worker(String name, String age) { super(name, age); // TODO Auto-generated constructor stub } @Override public void sayContent() { // TODO Auto-generated method stub System.out.println("I'm a work"); } } public class PersonDemo { public static void main(String args[]){ Person person1 = new Student("zhang san", "11", 100); Person person2 = new Worker("李四", "30"); person1.say(); person2.say(); } } //结果: //I'm a student socre=100.0 //I'm a work
接口:(一个特殊的类,JAVA中是由抽象方法和全局常量组成)
在java中使用interface定义一个接口
1、接口需要有子类,子类实现接口,通过implements关键字完成
2、可以简化如例子
3、一个类只能继承一个父类,但是可以实现多个接口
4、如果一个类既要实现接口又要继承抽象类,则必须按照以下形式完成
class 子类 extends 抽象类 implements 接口A,接口B....
5、一个抽象类可以实现多个接口,但是一个接口不能继承一个抽象类
6、一个接口不可以继承一个抽象类,但是可以同时继承多个接口
例子:
interface InterfaceDemo1 { public static String NAME = "INTERFACE_DEMO";//也可以写成 String NAME = "INTERFACE_DEMO"; public abstract void fun1();//一般写成 public void fun1(); 也可以写成 void fun1(); public abstract void fun2();//一般写成 public void fun2(); 也可以写成 void fun2(); } class InterfaceDemo2 implements InterfaceDemo1 { @Override public void fun1() { // TODO Auto-generated method stub System.out.println("----fun1---"); } @Override public void fun2() { // TODO Auto-generated method stub System.out.println("---fun2---" + NAME); } } public class InterfaceDemo { public static void main(String args[]) { InterfaceDemo2 interfaceDemo2 = new InterfaceDemo2(); interfaceDemo2.fun1(); interfaceDemo2.fun2(); } } // 结果: // ----fun1--- // ---fun2---INTERFACE_DEMO
接口的应用:
接口也可以像抽象类那样通过对象多态性进行对象实例化操作
接口实际上是作为一个标准存在的;
例如:电脑上实现了USB接口,U盘,打印机也都实现了
package com.demo; interface Usb{ public void start(); //开始工作 public void stop(); //停止工作 } class Computer{ public void connect(Usb usb){ usb.start(); usb.stop(); } } class Upan implements Usb{ @Override public void start() { // TODO Auto-generated method stub System.out.println("U盘。。。开始工作"); } @Override public void stop() { // TODO Auto-generated method stub System.out.println("U盘。。。。停止工作"); } } class Print implements Usb{ @Override public void start() { // TODO Auto-generated method stub System.out.println("打印机。。。开始工作"); } @Override public void stop() { // TODO Auto-generated method stub System.out.println("打印机。。。。停止工作"); } } public class InterfaceDemo { public static void main(String args[]){ Upan upan = new Upan(); Print print = new Print(); Computer computer = new Computer(); computer.connect(upan); computer.connect(print); } } //结果: //U盘。。。开始工作 //U盘。。。。停止工作 //打印机。。。开始工作 //打印机。。。。停止工作
接口和抽象类:
适配器设计模式:
接口的子类要实现全部抽象类的方法
但是如过希望可以根据自己的需要来选择性的覆写,那么应该用一个类(抽象类),先将接口实现了,但是所有的方法都属于空实现,之类再继承此类
package com.demo; public class AdapterDemo { public static void main(String args[]){ Windows window = new MyWindow(); window.open(); window.close(); } } /** *窗口接口 */ interface Windows{ public void open(); //打开窗口 public void close();//关闭窗口 public void icon();//最小化 public void unicon();//最大化 } /** * 窗口适配器 */ abstract class WindowsAdapter implements Windows{ @Override public void open() {}; @Override public void close() { System.out.println("关闭窗口 ---->close"); }; @Override public void icon() {}; @Override public void unicon() {}; } /** * 具体的窗口类 */ class MyWindow extends WindowsAdapter{ @Override public void open() { // TODO Auto-generated method stub super.open(); System.out.println("打开窗口----->open"); } } //结果: //打开窗口----->open //关闭窗口 ---->close
工厂设计模式:
所有接口的实例化对象都是通过工厂类取得的,那么客户端调用的时候根据传入的名称不同,完成的功能也不同。
package com.demo; import java.util.Scanner; public class FactoryDemo { public static void main(String args[]) { while (true) { Scanner scanner = new Scanner(System.in); String name = scanner.next(); if (name.equals("exit")) { break; } Fruit f = Factory.getFruit(name); if (null != f) { f.eat(); } } } } interface Fruit { public void eat(); } class Apple implements Fruit { @Override public void eat() { System.out.println("吃苹果"); } } class Orange implements Fruit { @Override public void eat() { System.out.println("吃橘子"); } } class Factory {// 工厂类 public static Fruit getFruit(String name) { Fruit f = null; if ("apple".equals(name)) { f = new Apple(); } if ("orange".equals(name)) { f = new Orange(); } return f; } }
所有接口的实例化对象都是通过工厂类取得的。那么客户端调用的时候根据传入的名称不同,完成的功能也不同。
if("orange".equles(className)){
f = new Orange();
}
在以上程序中将字符串写在前面,通过字符串的匿名对象调用方法。
代理设计模式:
现在有如下一种情况,生活情况
例如:张三属于老好人,有钱,之后李四向张阳借了 10000元钱,规定一年还
- 一年之后张三向李四讨债的时候李四不还
- 张三无奈之下找到王五,王五经营一家讨债公司,基本首付:刀子、手枪
- 王五为了成功的把钱讨回来,准备好了 小刀、绳子、手枪
- 李四害怕王五,还钱了
- 王五为了不让李四起诉 销毁了所有的罪证
张某——>范某——>讨债
package com.demo; public class ProxyMode { public static void main(String args[]){ DaiLi daiLi = new DaiLi(new ZhaiZhu()); daiLi.giveBack(); } } /** * 主要内容:讨债 */ interface TaoZhai{ public void giveBack(); } /** * 债主:张三 */ class ZhaiZhu implements TaoZhai{ @Override public void giveBack() { System.out.println("请把我的钱还给我"); } } /** * 代理讨债的人:王五 */ class DaiLi implements TaoZhai{ private TaoZhai taoZhai; public DaiLi(TaoZhai taoZhai) { super(); this.taoZhai = taoZhai; } /** * 讨债之前的准备 */ public void geiBackBefore(){ System.out.println("小刀、绳子、手枪"); } /** * 讨债事件 */ @Override public void giveBack() { // TODO Auto-generated method stub geiBackBefore(); this.taoZhai.giveBack(); geiBackAfter(); } /** * 讨债之后善后 */ public void geiBackAfter(){ System.out.println(" 销毁了所有的罪证"); } } //结果: //小刀、绳子、手枪 //请把我的钱还给我 // 销毁了所有的罪证
抽象类和接口的区别:
抽象类和接口同时可以使用的话,优先使用接口,因为接口可以避免单继承的局限
No | 比较点 | 抽象类 | 接口 |
1 | 组成 | 抽象方法、普通方法、常量、变量、构造方法、全局常量 | 抽象方法、全局变量 |
2 | 定义 | abstract | interface |
3 | 子类 | 子类通过extends继承抽象类 | 子类通过implements实现接口 |
4 | 限制 | 一个子类只能继承一个抽象类 | 一个子类可以同时实现多个接口 |
5 | 关系 |
|
|
6 | 设计模式 | 模版设计 | 工厂设计、代理设计 |
抽象类和接口一起可以 | 完成适配器设计 | ||
7 | 实例化 | 都是通过对象的多态性,通过 | 子类进行对象的实例化 |
8 | 实现限制 | 存在单继承局限 | 不存在此局限 |
9 | 特性 | 表示一个标准、一种能力 |