抽象类和接口抽象类
abstract class A{ // 是定义了一个抽象类
publicstatic final String FLAG = "CHINA" ; //全局常量
privateString name = "Cym" ; // 定义一个普通的属性
publicvoid setName(String name){
this.name = name ;
}
publicString getName(){
return this.name ;
}
publicabstract void print() ; // 定义抽象方法
};
包含一个抽象方法的类称为抽象类,抽象方法是只声明而未实现的方法,所有的抽象方法必须使用abstract关键字声明,所有的抽象类也需要abstract关键字声明。
abstract class A{ // 是定义了一个抽象类
publicstatic final String FLAG = "CHINA" ; //全局常量
privateString name = "Cym" ; // 定义一个普通的属性
publicvoid setName(String name){
this.name = name ;
}
publicString getName(){
return this.name ;
}
publicabstract void print() ; // 定义抽象方法
};
class B extends A{ // 继承抽象类,因为B是普通类,所以必须覆写全部抽象方法
publicvoid print(){
System.out.println("FLAG = " +FLAG) ;
System.out.println("姓名 = " + super.getName()) ;
}
};
对于抽象类来将,不能直接实例化的操作,但是可以声明,如果要使用抽象类,则必须依靠子类,抽象类是必须被子类继承,而且被继承的子类需要实现抽象中的全部抽象方法。
问题:
抽象类是否可以使用final关键字修饰呢?
抽象类必须被子类继承。
被final修饰的类不能被继承。
所以得出结论,抽象类不能使用final关键子修饰。
抽象类是否可以存在构造方法?
abstract classA{ // 是定义了一个抽象类
public A(){
System.out.println("A、抽象类中的构造方法。") ;
}
};
class B extendsA{ // 继承抽象类,因为B是普通类,所以必须覆写全部抽象方法
public B(){
super();
System.out.println("B、子类中的构造方法。") ;
}
};
public classAbstractDemo03{
public static void main(String args[]){
Bb = new B() ;
}
};
抽象类中允许有构造方法,但是此构造方法不能直接调用的,是交给子类调用的,子类对象的实例化过程中,永远是先调用父类中的构造方法。
抽象类就是比普通类多了一个抽象方法而已。
抽象类属性如何初始化?
abstract class Person{
privateString name ; // 定义name属性
privateint age ; // 定义age属性
publicPerson(String name,int age){
this.name = name ;
this.age = age ;
}
publicvoid setName(String name){
this.name = name ;
}
publicvoid setAge(int age){
this.age = age ;
}
publicString getName(){
return this.name ;
}
publicint getAge(){
return this.age ;
}
publicabstract String getInfo() ; // 抽象方法
};
使用super
class Student extends Person{
privateString school ;
publicStudent(String name,int age,String school){
super(name,age) ; // 指定要调用抽象类中有两个参数的构造方法
this.school = school ;
}
publicvoid setSchool(String school){
this.school = school ;
}
publicString getSchool(){
return this.school ;
}
publicString getInfo(){
return "姓名:" + super.getName() +
";年龄:" + super.getAge() +
";学校:" + this.getSchool() ;
}
};
public class AbstractDemo04{
publicstatic void main(String args[]){
Student stu = new Student("张三",30,"清华大学") ;
System.out.println(stu.getInfo()) ;
}
};
抽象类中的属性如果要想初始化,则肯定还要依赖与构造方法。
接口
接口是一个特殊的类,在java中接口是由抽象方法和全局常量组成。
在java中使用interface定义一个接口
interface A{ // 定义接口A
publicstatic final String AUTHOR = "CYM" ; //全局常量
publicabstract void print() ; // 抽象方法
publicabstract String getInfo() ; // 抽象方法
}
在此接口中定义两个抽象方法,一个全局常量,那么接口与抽象类一样,需要有子类,那么子类此时不再称为继承类,而是实现类,通过implements关键字实现完成。
接口的方法和属性永远是pubic修饰符
默认是方法是abstract
属性是 static final
既然接口从定义上已经明确了要求是由抽象方法和全局常量组成,那么在接口定义的时候就可以简化操作
interface A{ // 定义接口A
StringAUTHOR = "Cym" ; // 全局常量
voidprint() ; // 抽象方法
StringgetInfo() ; // 抽象方法
}
一个类是虽然值能继承一个父类,但是一个类可以同时实现多个接口。
如果一个类既要实现接口又要继承抽象类的话,则必须按照一下的形式完成。
Class 子类extends 抽象类 implements 接口A,接口B,......{}
interface A{ // 定义接口A
publicString AUTHOR = "CYM" ; //全局常量
publicvoid print() ; // 抽象方法
publicString getInfo() ; // 抽象方法
}
abstract class B{ // 定义抽象类B
publicabstract void say() ; // 定义抽象方法
}
class X extends B implements A{ // X类线继承B类,再实现A接口
publicvoid say(){
System.out.println("HelloWorld!!!") ;
}
publicString getInfo(){
return "HELLO" ;
}
publicvoid print(){
System.out.println("作者:" + AUTHOR) ;
}
};
public class InterfaceDemo04{
publicstatic void main(String args[]){
X x = new X() ; // 实例化子类对象
x.say() ;
x.print() ;
}
};
接口里面的方法可以简写方法不写abstract关键字,但是抽象类里一定要修abstract关键字。
interface A{ // 定义接口A
publicString AUTHOR = "CYM" ; //全局常量
publicvoid print() ; // 抽象方法
publicString getInfo() ; // 抽象方法
}
abstract class B implements A{ // 定义抽象类B,实现接口A
publicabstract void say() ; // 定义抽象方法
}
class X extends B{ // X类线继承B类
publicvoid say(){
System.out.println("HelloWorld!!!") ;
}
publicString getInfo(){
return "HELLO" ;
}
publicvoid print(){
System.out.println("作者:" + AUTHOR) ;
}
};
public class InterfaceDemo05{
publicstatic void main(String args[]){
X x = new X() ; // 实例化子类对象
x.say() ;
x.print() ;
}
};
一个抽象类可以实现多个接口,但是一个接口不能继承一个抽象类。
interface A{ // 定义接口A
publicString AUTHOR = "CYM" ; //全局常量
publicvoid printA() ; // 抽象方法
}
interface B{
publicvoid printB() ;
}
interface C extends A,B{
publicvoid printC() ;
}
class X implements C{ // X类线继承B类
publicvoid printA(){
System.out.println("A、Hello World!!!") ;
}
publicvoid printB(){
System.out.println("B、Hello MLDN") ;
}
publicvoid printC(){
System.out.println("C、Hello LXH") ;
}
};
public class InterfaceDemo06{
publicstatic void main(String args[]){
X x = new X() ; // 实例化子类对象
x.printA() ;
x.printB() ;
x.printC() ;
}
};
一个接口虽然不可以继承一个抽象类,但是一个接口却可以同时继承多个接口。
对象多态性
接口和抽象类的基本概念完成了,下面最重要的就是对象的多态性,是整个java中最重要的一个部分,因为有多态性的存在,才可以让程序变的更加灵活。
多态性是面向对象的最后一个特征:
方法的重载和方法的覆写实际上就属于多态行的一种体现。
真正的多态性中还包含了一种为对象多态性概念。
对象多态性主要指的是,子类和父类对象的相互转换关系。
向上转型:父类 父类对象 = 子类实例 --》自动完成
向下转型:子类 子类对象 = (子类)父类实例 --》强制完成
classA{
publicvoid fun1(){
System.out.println("1、A类 --> public void fun1(){}") ;
}
publicvoid fun2(){
this.fun1() ;
}
};
class B extends A{
publicvoid fun1(){ // 将方法覆写了
System.out.println("2、B类 --> public void fun1(){}") ;
}
publicvoid fun3(){ // 此操作为子类自己定义的,父类中不存在
System.out.println("3、B类 --> public void fun3(){}") ;
}
};
public class PolDemo01{
publicstatic void main(String args[]){
A a = new B() ; // 发生向上转型关系,子类实例 --> 父类实例
a.fun2() ;
}
};
父类对象 = 子类实例(向上转型)
只能使用父类有的方法。(子类如果覆写则使用子类覆写的方法)
class A{
publicvoid fun1(){
System.out.println("1、A类 --> public void fun1(){}") ;
}
publicvoid fun2(){
this.fun1() ;
}
};
class B extends A{
publicvoid fun1(){ // 将方法覆写了
System.out.println("2、B类 --> public void fun1(){}") ;
}
publicvoid fun3(){ // 此操作为子类自己定义的,父类中不存在
System.out.println("3、B类 --> public void fun3(){}") ;
}
};
public class PolDemo02{
publicstatic void main(String args[]){
A a = new B() ; // 发生向上转型关系,子类实例 --> 父类实例
B b = (B)a ; // 发生向下转型关系,强制
b.fun3() ;
b.fun2() ;
}
};
父类对象 = 子类实例
子类对象 = (子类)父类对象(向下转型)
class A{
publicvoid fun1(){
System.out.println("1、A类 --> public void fun1(){}") ;
}
publicvoid fun2(){
this.fun1() ;
}
};
class B extends A{
publicvoid fun1(){ // 将方法覆写了
System.out.println("2、B类 --> public void fun1(){}") ;
}
publicvoid fun3(){ // 此操作为子类自己定义的,父类中不存在
System.out.println("3、B类 --> public void fun3(){}") ;
}
};
public class PolDemo03{
publicstatic void main(String args[]){
A a = new A() ;
B b = (B)a ;
b.fun2() ;
}
};
会产生ClassCastException,表示转换异常,造成的根本原因是两个没有关系的类进行相互的对象操作。
观察对象多态性的作用:
假如:现在要设计一个方法,那么此方法可以接受A类的所有子类的实例。
如果现在不使用对象多态性的概念完成
class A{
public void fun1(){
System.out.println("1、A类 -->public void fun1(){}") ;
}
public void fun2(){
this.fun1() ;
}
};
class B extends A{
public void fun1(){ // 将方法覆写了
System.out.println("2、B类 -->public void fun1(){}") ;
}
public void fun3(){ // 此操作为子类自己定义的,父类中不存在
System.out.println("3、B类 -->public void fun3(){}") ;
}
};
class C extends A{
public void fun1(){ // 将方法覆写了
System.out.println("4、C类 -->public void fun1(){}") ;
}
public void fun4(){ // 此操作为子类自己定义的,父类中不存在
System.out.println("5、C类 -->public void fun4(){}") ;
}
};
public class PolDemo04{
public static voidmain(String args[]){
fun(new B()) ;
fun(new C()) ;
}
public static void fun(Bb){
b.fun2() ;
b.fun3() ;
}
public static void fun(Cc){
c.fun2() ;
c.fun4() ;
}
};
以上的方式是通过重载完成,那么使用以上方法完成会存在以上的缺点,如果现在A类的子类有N个,那么方法就要重载N次,而且每次增加子类的时候都需要修改代码本身。
所以,此时使用对象多态性就可以很好的解决此类问题,因为所有的对象都会发生自动的向上转型操作。
class A{
public void fun1(){
System.out.println("1、A类 -->public void fun1(){}") ;
}
public void fun2(){
this.fun1() ;
}
};
class B extends A{
public void fun1(){ // 将方法覆写了
System.out.println("2、B类 -->public void fun1(){}") ;
}
public void fun3(){ // 此操作为子类自己定义的,父类中不存在
System.out.println("3、B类 -->public void fun3(){}") ;
}
};
class C extends A{
public void fun1(){ // 将方法覆写了
System.out.println("4、C类 -->public void fun1(){}") ;
}
public void fun4(){ // 此操作为子类自己定义的,父类中不存在
System.out.println("5、C类 -->public void fun4(){}") ;
}
};
public class PolDemo05{
public static voidmain(String args[]){
fun(new B()) ;
fun(new C()) ;
}
public static void fun(Aa){
a.fun2() ;
}
};
class A{
public void fun1(){
System.out.println("1、A类 -->public void fun1(){}") ;
}
public void fun2(){
this.fun1() ;
}
};
class B extends A{
public void fun1(){ // 将方法覆写了
System.out.println("2、B类 -->public void fun1(){}") ;
}
public void fun3(){ // 此操作为子类自己定义的,父类中不存在
System.out.println("3、B类 -->public void fun3(){}") ;
}
};
class C extends A{
public void fun1(){ // 将方法覆写了
System.out.println("4、C类 -->public void fun1(){}") ;
}
public void fun4(){ // 此操作为子类自己定义的,父类中不存在
System.out.println("5、C类 -->public void fun4(){}") ;
}
};
public class PolDemo08{
public static voidmain(String args[]){
fun(new B()) ;
fun(new C()) ;
}
public static void fun(Aa){
a.fun2() ;
if(a instanceof B){
B b = (B)a ;
b.fun3() ;
}
if(a instanceof C){
C c = (C)a ;
c.fun4() ;
}
}
};
如果要使用子类自身的方法为了保证对象向下转型操作正确,在操作前最好加上instanceof关键字判断。
在继承关系中,父类的设计很重要,只要父类的设计合理了,则代码开发非常简便。
抽象类的应用
从对象多态性的概念来看,子类为父类实例化是一个比较容易的操作,以为可以发生自动的向上转型关系,那么调用的方法永远是被子类覆写过的方法。
那么,此时就可以利用此概念通过对象多态性为抽象类实例化。
抽象类可以实现方法,当很多类有相同方法和并且相同实现的时候,我们就可以用抽象类。当然也可以覆写。
抽象类本身最大的用处就是在于模版设计。
接口的应用
接口也可以像抽象类那样通过多态性进行对象的实例化操作。
抽象类可以用于定义模版操作,但是接口呢?
接口实际上是作为一个标准存在的。
接口不可以的实现方法,但很多类只要有相同方法操作的时候,我们就可以用接口作为一种标准。
接口和抽象类适配器设计模式
正常情况下一个接口的子类要实现全部的抽象方法
interface Window{
publicvoid open() ; // 打开窗口
publicvoid close() ; // 关闭窗口
publicvoid icon() ; // 最小化
publicvoid unicon() ; // 最大化
}
Class MyWindow implements Window{
}
在MyWindow类此时肯定要覆写全部的抽象方法,但是现在希望可以根据自己的需要来选择覆写,那么该怎么实现?
用一个类先将接口实现了,但是所有的方法都属于空实现,之后再继承此类。
应该使用抽象类,因为抽象类也不能直接使用。
interfaceWindow{
public void open() ; // 打开窗口
public void close() ; // 关闭窗口
public void icon() ; // 最小化
public void unicon() ; // 最大化
}
abstract classWindowAdapter implements Window{
public void open(){}
public void close(){}
public void icon(){}
public void unicon(){}
};
class MyWindowextends WindowAdapter{
public voidopen(){
System.out.println("打开窗口!");
}
};
public classAdpaterDemo{
public static void main(String args[]){
Windowwin = new MyWindow() ;
win.open();
}
}
工厂设计模式
interface Fruit{
publicvoid eat() ;
}
class Apple implements Fruit{
publicvoid eat(){
System.out.println("吃苹果。。。") ;
}
};
class Orange implements Fruit{
publicvoid eat(){
System.out.println("吃橘子。。。") ;
}
};
Public class interDemo{
Public staticvoid main(String args[]){
Fruit f = new Apple();
F.eat();
}
}
以上的程序如果开发的话是存在问题?
一直强调:主方法实际上就是一个客户端。客户端的代码越简单越好。
interface Fruit{
publicvoid eat() ;
}
class Apple implements Fruit{
publicvoid eat(){
System.out.println("吃苹果。。。") ;
}
};
class Orange implements Fruit{
publicvoid eat(){
System.out.println("吃橘子。。。") ;
}
};
class Factory{ // 工厂类
publicstatic Fruit getFruit(String className){
Fruit f = null ;
if("apple".equals(className)){
f= new Apple() ;
}
if("orange".equals(className)){
f= new Orange() ;
}
return f ;
}
};
public class InterDemo{
publicstatic void main(String args[]){
Fruit f = Factory.getFruit(args[0]) ;
if(f!=null){
f.eat();
}
}
}
所有接口的实例化对象都是工厂类取得的。那么客户端调用的时候根据传入的名称不同,完成不同的功能。
代理设计模式
interface Give{
publicvoid giveMoney() ;
}
class RealGive implements Give{
publicvoid giveMoney(){
System.out.println("把钱还给我。。。。。") ;
}
};
class ProxyGive implements Give{ // 代理公司
privateGive give = null ;
publicProxyGive(Give give){
this.give = give ;
}
publicvoid before(){
System.out.println("准备:小刀、绳索、钢筋、钢据、手枪、毒品") ;
}
publicvoid giveMoney(){
this.before() ;
this.give.giveMoney() ; // 代表真正的讨债者完成讨债的操作
this.after() ;
}
publicvoid after(){
System.out.println("销毁所有罪证") ;
}
};
public class ProxyDemo{
publicstatic void main(String args[]){
Give give = new ProxyGive(new RealGive());
give.giveMoney() ;
}
};
当两个类同时实现一个接口,一个类需要另外一个类代理才能实现该功能,这就叫代理模式。
抽象类与接口的区别
NO |
比较点 |
抽象类 |
接口 |
|
1 |
组成 |
抽象方法、普通方法、常量、变量、构造、方法、全局变量 |
抽象方法、全局常量 |
|
2 |
定义 |
Abstract |
interface |
|
3 |
子类 |
子类通过extends继承抽象类 |
子类通过implements实现接口 |
|
4 |
限制 |
一个子类只能继承一个抽象类 |
一个子类能够同时实现多个接口 |
|
5 |
关系 |
一个抽象类可以实现多个接口 一个抽象类中可以包含多个接口 |
一个接口不能继承一个抽象类 一个接口可以包含多个抽象类 |
|
6 |
设计模式 |
模版设计 |
工厂模式、代理模式 |
|
7 |
实例化 |
都是通过对象的多态性、通过子类进行对象实例化操作 |
||
8 |
实现限制 |
存在单继承局限 |
不存在单继承局限 |
|
9 |
特性 |
一个标准、一种能力 |
||
如果抽象类和接口同时都可以使用的话、优先接口,以为接口可以避免单继承的局限。
抽象类包含接口
abstract class A{
publicabstract void fun() ;
interfaceB{ // 内部接口
public void print() ;
}
};
class X extends A{
publicvoid fun(){
System.out.println("****************");
}
classY implements B{
public void print(){
System.out.println("===================");
}
};
};
public class TestDemo01{
publicstatic void main(String args[]){
A a = new X() ;
a.fun() ;
A.B b = new X().new Y() ;
b.print() ;
}
};
接口包含抽象类
interface A{
publicvoid fun() ;
abstractclass B{ // 内部抽象类
public abstract void print() ;
}
};
class X implements A{
publicvoid fun(){
System.out.println("****************");
}
classY extends B{
public void print(){
System.out.println("===================");
}
};
};
public class TestDemo02{
publicstatic void main(String args[]){
A a = new X() ;
a.fun() ;
A.B b = new X().new Y() ;
b.print() ;
}
};
ym——抽象与接口包含(工厂+适配器+代理)模式讲解