java中的接口跟抽象类区别

java中的接口和抽象类区别
http://hanhongke123.blog.163.com/blog/static/62223494201081433426189/

首先,我们来看一下抽象类的概念,java编程思想中说“万物皆对象”,我们知道所有的对象都是通过类来描绘的,但是反过来却不是这样。并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。抽象类是表征我们对问题领域进行分析、设计中得出的抽象概念,是对一系列看上去不同,但是本质上相同的具体概念的抽象。   

       好比,我们都知道三角形是一个形状,世界上有三角形这样具体的东西,但是确没有形状这样具体的东西,我们要描述这个形状的概念就要用到抽象类。因此在java中抽象类是不允许被实例化的。
      在面向对象领域,抽象类主要用来进行类型隐藏。那什么是类型隐藏呢?我们可以构造出一个固定的一组行为的抽象描述,但是这组行为却能够有任意个可能的具体实现方式。这个抽象描述就是抽象类,而这一组任意个可能的具体实现则表现为所有可能的派生类。

      好比,动物是一个抽象类,人、猴子、老虎就是具体实现的派生类,我们就可以用动物类型来隐藏人、猴子和老虎的类型。


      再来看一下接口,接口是什么呢?Java中的接口是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为(功能)。接口是一种特殊形式的抽象类。

  
   抽象类和接口有很大的区别:

        首先,抽象类在Java语言中表示的是一种继承关系,一个类只能使用一次继承关系,但是,一个类却可以实现多个接口。也许,这是Java语言的设计者在考虑Java对于多重继承的支持方面的一种折中考虑吧。
         其次,在抽象类的定义中,我们可以赋予方法的默认行为。但是在接口的定义中,方法却不能拥有默认行为,为了绕过这个限制,必须使用委托,但是这会 增加一些复杂性,有时会造成很大的麻烦。
        已经提到过,抽象类在Java语言中体现了一种继承关系,要想使得继承关系合理,父类和派生类之间必须存在”is a”关系,即父类和派生类在概念本质上应该是相同的。对于接口来说则不然,并不要求接口的实现者和接口定义在概念本质上是一致的,仅仅是实现了接口定义的契约而已。接口表示的是”like a”关系。
使用抽象类来定义允许多个实现的类型,比使用接口有一个明显的优势:抽象类的演化比接口的演化要容易的多。在后续的发行版中,如果希望在抽象类中增加一个方法,只增加一个默认的合理的实现即可,抽象类的所有实现都自动提供了这个新的方法。对于接口,这是行不通的。虽然可以在骨架实现类中增加一方法的实现来解决部分问题,但这不能解决不从骨架实现类继承的接口实现的问题。由此,设计公有的接口要非常谨慎,一旦一个接口被公开且被广泛实现,对它进行修改将是不可能的。
所以,使用接口还是抽象类,取决于我们对问题的概念的本质理解和设计的意图。
//---------------------------------
        类描述了一个实体,包括实体的状态,也包括实体可能发出的动作。
  接口定义了一个实体可能发出的动作。但是只是定义了这些动作的原型,没有实现,也没有任何状态信息。
  所以接口有点象一个规范、一个协议,是一个抽象的概念;而类则是实现了这个协议,满足了这个规范的具体实体,是一个具体的概念。
  从程序角度,简单理解,接口就是函数声明,类就是函数实现。需要注意的是同一个声明可能有很多种实现。
  1、接口中定义类方法的原型,但是不能说是空方法,因为空方法的意思是有实现体,只不过实现体是空操作。实际上接口没有定义任何实现体。具体的实现体都是在实现接口的类中,接口只是定义了这些方法的调用方式。
  你当然也可以不用接口,直接在类里面写方法,但是如果你的一组方法需要在很多类里实现,那么把它们抽象出来,做成一个接口规范,不是更好么?
  2、一个类描述了一个实体,这个实体可能是一个复杂的对象,它的动作很多,如果把这些动作分类,用接口a定义其中的某一组动作,接口b定义其中的另外一组动作,这样的结构,比较清楚。
  这种方式具备了多继承的优点,避免了多继承的缺陷。实际上在历史上,接口在很大程度上,是为了解决多继承带来的种种问题而设计出来的。
  3、包中那些已定义的接口,怎么知道那里面定义了什么方法。
  接口里定义了方法的输入输出,这些都是协议,具体的实现都在每个类中。对于很多只需要抽象接口的地方,不需要知道具体的类是什么,只要这个类实现了这个接口就可以了。

当然,以上只是对接口的初步认识,在对面向对象程序设计有更深入的认识以后,会发现接口有更广泛的用途。

另外,抽象类不能被实例化,也就是说,不能创建抽象类的任何对象。必须创建抽象类的子类,然后再创建子类的对象。一个接口可以继承多个接口,一个类可以实现多个接口。
本文出自 51CTO.COM技术博客





***************************************************************************************************************************************************

1、抽象类
       抽象类实际上也是一个类,只是与之前的普通类相比,在抽象类中多了抽象方法。
       抽象方法是只声明而未实现的方法,所有的抽象方法必须使用abstract关键字声明,包含抽象方法的类也必须使用abstract class声明。
一个抽象类的定义
abstract class A{
         private String name = "WWW" ;
         public void fun(){
                   // 此处定义了一个普通方法
                   System.out.println("Hello World!!!") ;
         }
         public abstract void print() ;
}; 
     

可以发现抽象方法后面没有“{}”,则表示方法没有实现。
       如果对抽象方法直接实例化,则会出现无法实例化的错误。
abstract class A{
         private String name = "WWW" ;
         public void fun(){
                   // 此处定义了一个普通方法
                   System.out.println("Hello World!!!") ;
         }
         public abstract void print() ;
};
public class Demo01{
         public static void main(String args[]){
                   A a = new A() ;
         }
}; 

抽象类的使用原则:
       1、  抽象类必须有子类,抽象类必须被继承
       2、  抽象类的子类如果不是抽象类的话,则必须覆写里面的全部抽象方法。
       3、  抽象类不能直接实例化,必须依靠子类完成。
进一步完善之前的程序:
abstract class A{
         private String name = "WWW" ;
         public void fun(){
                   // 此处定义了一个普通方法
                   System.out.println("Hello World!!!") ;
         }
         public abstract void print() ;
};
class B extends A{
         // 覆写抽象方法
         public void print(){
                   System.out.println("**********************") ;
         }
};
public class Demo02{
         public static void main(String args[]){
                   B b = new B() ;
                   b.print() ;
                   b.fun() ;
         }
}; 

讨论问题:
       1、  能否用final修饰一个抽象类呢?
              · 因为抽象类必须被子类继承,而被final修饰的类不能有子类。所以不能
       2、  抽象类中能否有构造方法呢?可以有
abstract class Person{
         private String name ;
         private int age ;
         // 单独按一个类来说,应该可以直接在构造方法中初始化
         public Person(String name,int age){
                   this.name = name ;
                   this.age = age ;
         }
         public abstract String getInfo() ;
         public String getName(){
                   return this.name ;
         }
         public int getAge(){
                   return this.age ;
         }
};
class Student extends Person{
         private String school ;
         public Student(String name,int age,String school){
                   super(name,age) ;
                   this.school = school ;
         }
         public String getInfo(){
                   return "姓名:"+super.getName()+",年龄:"+super.getAge()+",学校:"+this.school ;
         }
};
public class Demo03{
         public static void main(String args[]){
                   Student stu = new Student("张三",30,"北京大学") ;
                   System.out.println(stu.getInfo()) ;
         }
}; 

抽象类中可以有构造方法,但是要求在没有无参构造方法的时候,子类必须明确的调用父类中的构造方法。
回顾:子类对象的实例化过程
· 子类对象实例化的时候默认会先去调用父类中的无参构造方法,如果父类中没有无参构造,则可以通过super指定调用父类中的其他构造方法。
注意:
       一个类只可以继承一个抽象类,属于单继承。
2、接口
       接口定义:
              · 只包含抽象方法和全局常量的类称为接口。
              · 接口使用interface进行定义。
interface A{
         public static final String INFO = "HELLO" ;
         public abstract void print() ;
} 
      
接口定义完之后,一个接口也必须依靠其子类使用,子类继承接口的概念称为实现。格式如下:
              class 子类 implements 接口名称{}
       接口的子类如果不是抽象类的话,则也必须覆写里面的全部抽象方法。
interface A{
         public static final String INFO = "HELLO" ;
         public abstract void print() ;
}
class B implements A{
         public void print(){
                   System.out.println(INFO) ;
         }
};
public class Demo04{
         public static void main(String args[]){
                   B b = new B() ;
                   b.print() ;
         }
}; 

       接口与抽象类相比,有一个优点:说一个子类只能继承一个父类,但是可以同时实现多个接口,也就说是通过接口完成多继承。
       class 子类 implements 接口A,接口B
interface A{
         public static final String INFO = "HELLO" ;
         public abstract void print() ;
}
interface C{
         public static final String PARAM = "WWW" ;
         public abstract void fun() ;
}
class B implements A,C{
         public void print(){
                   System.out.println(INFO) ;
         }
         public void fun(){
                   System.out.println(PARAM) ;
         }
};
public class Demo05{
         public static void main(String args[]){
                   B b = new B() ;
                   b.print() ;
                   b.fun() ;
         }
}; 

       问题:
既然,接口中的一切方法都是抽象方法,接口中的一切变量都是全局常量,那么实际上接口就可以简化成如下的形式定义。
interface A{
         // public static final String INFO = "HELLO" ;
         String INFO = "HELLO" ;
         // public abstract void print() ;
         void print() ;     //à 此处虽然没有明确的写出权限,但实际上权限是public
} 

       一定要明确:接口中的一切方法都是public访问权限,所以在子类实现方法的时候访问权限必须是public。写与不写是一样的。所以有时候为了避免此种情况,还是建议写上:public
         public void print() ;

       那么如果一个类继承继承一个抽象类又要实现一个接口,则必须按照以下格式完成:
       class 子类 extends 父类(一般都是抽象类) implements 接口A,接口B

interface A{
         // public static final String INFO = "HELLO" ;
         String INFO = "HELLO" ;
         // public abstract void print() ;
         void print() ;
}
abstract class X{
         public String param = "hello" ;
         abstract void fun() ;
};
class B extends X implements A{
         public void print(){
                   System.out.println(INFO) ;
         }
         void fun(){
                   System.out.println(INFO) ;
                   System.out.println(param) ;
         }
};
public class Demo07{
         public static void main(String args[]){
                   B b = new B() ;
                   b.print() ;
         }
}; 


开发原则:
       在开发中一定要记住,一个类往往很少去继承一个已经实现好的类,即:普通类之间不能互相继承。

注意点:
       1、  一个抽象类可以实现多个接口,但是一个接口不能继承一个抽象类。
interface A{
         // public static final String INFO = "HELLO" ;
         String INFO = "HELLO" ;
         // public abstract void print() ;
         void print() ;
}
abstract class X implements A{
         public String param = "hello" ;
         abstract void fun() ;
}; 
      
2、  一个接口可以同时继承多个接口,即:实现多继承关系
              interface 子接口 extends 父接口A,父接口B,父接口C
interface A{
         public void printA() ;
}
interface B{
         public void printB() ;
}
interface C{
         public void printC() ;
}
interface X extends A,B,C{
         public void printX() ;
};
class Y implements X{
         public void printA(){}
         public void printB(){}
         public void printC(){}
         public void printX() ;
}; 




抽象类与接口的实际应用{百分百的重点}

开发原则:
       在类的开发之中,一个类不会去继承一个已经实现好的类,只会继承抽象类或实现接口。
       即:以下的代码是不应该出现在程序之中的:
class A{}
class B extends A{} 


3、抽象类实际应用
       抽象类本身是不能直接实例化的。因为其本身包含抽象方法。
       但是抽象类的时候符合继承关系,只要有继承关系,则肯定会存在对象的向上或向下转型的问题,一但对象发生了向上转型,则肯定一切的方法以被子类覆写过的方法为准。
abstract class A{
         public abstract void fun() ;
};
class B extends A{
         public void fun(){
                   System.out.println("Hello World!!!") ;
         }
};
public class Demo32{
         public static void main(String args[]){
                   A a = new B() ;
                   a.fun() ;
         }
}; 
      
从以上代码之中可以发现,抽象类可以实例化,但是需要通过对象的多态性,通过子类进行实例化操作。
实际上抽象类就是提供了此种类型的代码结构。
例如:人分为工人和学生,工人和学生都有说话方法,但是说话的内容要由工人或学生决定,所以此时就可以使用抽象类完成此种功能。
abstract class Person{
         private String name ;
         private int age ;
         public Person(String name,int age){
                   this.name = name ;
                   this.age = age ;
         }
         public void say(){
                   System.out.println(this.getContent()) ;
         }
         public String getName(){
                   return this.name ;
         }
         public int getAge(){
                   return this.age ;
         }
         public abstract String getContent() ;
};
class Worker extends Person{
         private float salary ;
         public Worker(String name,int age,float salary){
                   super(name,age) ;
                   this.salary = salary ;
         }
         public String getContent(){
                   return "工人说 --> 姓名:"+this.getName()+",年龄:"+this.getAge()+",工资:"+this.salary ;
         }
};
class Student extends Person{
         private float score ;
         public Student(String name,int age,float score){
                   super(name,age) ;
                   this.score = score ;
         }
         public String getContent(){
                   return "学生说 --> 姓名:"+this.getName()+",年龄:"+this.getAge()+",成绩:"+this.score ;
         }
};
public class Demo33{
         public static void main(String args[]){
                   Person p = null ;
                   // p = new Student("张三",20,99.0f) ;
                   p = new Worker("张三",20,999.0f) ;
                   p.say() ;
         }
}; 

4、接口的实际应用
总的使用原则:接口的作用就是将方法名称暴露给远程用户。
       接口与抽象类一样,如果要想正确的时候也需要通过子类进行实例化操作。
如下代码所示:
interface A{
         public void print() ;
}
class B implements A{
         public void print(){
                   System.out.println("Hello World!!!") ;
         }
};
public class Demo35{
         public static void main(String args[]){
                   A a = new B() ;
                   a.print() ;
         }
}; 

接口的实际应用:定义标准。
       以USB接口为例:
interface USB{
         public void start() ;
         public void stop() ;
}
class MainBoard{
         public void plugIn(USB usb){
                   usb.start() ;
                   usb.stop() ;
         }
};
class Mp3 implements USB{
         public void start(){
                   System.out.println("MP3开始工作。") ;
         }
         public void stop(){
                   System.out.println("MP3停止工作。") ;
         }
};
class Print implements USB{
         public void start(){
                   System.out.println("打印机开始工作。") ;
         }
         public void stop(){
                   System.out.println("打印机停止工作。") ;
         }
};
public class Demo36{
         public static void main(String args[]){
                   MainBoard mb = new MainBoard() ;
                   mb.plugIn(new Mp3()) ;
                   mb.plugIn(new Print()) ;
         }
}; 






抽象类与接口的区别(☆☆) 区别点 抽象类 接口
定义 abstract class 抽象类名称{} interface 接口名称{}
概念 包含一个抽象方法的类就是抽象类,除此之外还包含常量、变量、普通方法、构造方法 只包含全局常量和抽象方法的类称为接口
使用 需要通过子类继承
class 子类 extends 父类 需要通过子类实现
class 子类 implements 接口
关系 一个抽象类可以实现多个接口,一个接口不能继承一个抽象类
作用 提供了一个模板 提供了一个标准,或者说表示了一种能力
设计模式 模板设计模式 工厂设计模式、代理设计模式
适配器设计模式
限制 抽象类有单继承局限 无此局限
应用 如果抽象类与接口同时都可以使用,优先使用接口
特殊点 一个抽象类可以包含一个接口或一个抽象类 一个接口中也可以包含抽象类或接口