3、类与对象之抽象类、接口、内部类

抽象类与接口:

这两个概念总是被放在一起讨论,因为他们有很多相似的地方,可以说接口本身就是完全抽象的,它要比抽象类更加“抽象”,为什么这么说?抽象类是一种类,里面除了有抽象方法外,还可以有具体的方法,而接口里面必须都是抽象的方法(有时可以在接口里定义类,后面会讲),尽管有时并没有显示的用abstract 关键字声明。此处我们提到抽象方法,在Java中,凡是声明为形如:abstract void function()的方法,都是抽象方法,包含抽象方法的类就是抽象类,可以这么总结:抽象类中是可以全是实体方法;也可以全是抽象方法。有抽象方法的类必须是抽象类;

 

当我们继承抽象类时,必须重写其抽象方法,所以抽象类不能被声明为final类型的,因为加final关键字的类保证不能被继承,抽象类只能被继承,不能被实例化(只要是abstract声明的类)!

声明为interface的类为接口,比抽象类更加抽象的一种机制。在接口中,我们不能提供任何实现,所有方法必须都是抽象的,可以不加 abstract关键字,但是编译器对于接口中的方法,都是直接按抽象方法处理的。我们通过implements来实现某个接口。当我们实现某个接口时, 必须重写其所有方法。

 

Java多接口实现

 

interface为我们提供了一种将抽象方法与实体方法分离的结构,但是interface的作用远不止此,在Java中接口解决了一个非常重要的问题:多继承。在C++中,实现多重继承是比较简单的事儿,但是Java继承机制不允许多重继承,所以如果想要整合不同类的功能,就需要使用接口:

总结下使用接口的好处:

1、接口可以实现向上转型,多个具有共同属性的类可以将它们的共同点提取出来,做成抽象,这样层次分明,统一管理。

 

class A implements interA,interB,interC{
       @overide 
        somemethod(){... ...}
}
class B{
       method(interA a){a.fun1()};
       method(interB a){a.fun2()};
       method(interC a){a.fun3()};
       main(){method(new A);}
}
两个接口定义一样的方法被同一个类实现,调用执行时是同一个方法;

 

 

 

2、接口不具有任何实体方法,最适合做基类。

 

总结一下抽象类与接口的区别和联系:

 

a)  抽象类是类,可以有实体方法。

 

b)  抽象类不能实现多继承,而接口可以。

 

c)  如果需要创建不带任何方法定义和成员变量的基类,则使用接口,如果类中需要有部分具体的实现,则使用抽象类。

 

d)  如果事先想要将某类设计为一个基类,那么首选接口。

接口可以通过继承(extends)接口,来拓展功能。

接口中的变量(域)默认是public  final static 的
因此在interface中声明的变量建议大写的,声明的时候必须初始化,使用的时候不能被更改
显式声明的 public  final static String NAME;
隐式声明的 String NAME;

 

内部类

 

内部类的意思就是将类的定义放在另一个类的内部。有时合理的内部类使用会使代码更加简洁,令程序更加巧妙。作为外部类的成员,内部类可以访问外部类私有的成员变量。我们先来看看内部类的创建,分这么几种情况:

1、在外部类非静态方法 创建内部类实例。

class InnerClass {  
    class A{  
        int a = 10;  
        void b(){  
            System.out.println("this is A.b()!");  
        }  
    }  
    A getA(){
     A a=new A();       
    return a;         //外部通过调用该方法得到局部方法的值,局部变量a在外面失效;
    }
}
public class Extends {	
  public static void main(String[] args){	  
	  new InnerClass().getA().b();
  }
} 

 

2、在外部类的静态方法中创建内部类的实例。

当在外部类的静态方法中创建内部类时,内部类也必须是静态的,形如:static  class  A{  },

这里为什么class A 一定要加上static?

public class InnerClass {  
	static class A{  
        int a = 10;  
        void b(){  
            System.out.println("this is A.b()!");  
        }  
    }  
    public static void main(String[] args) {  
        InnerClass.build().b();  
    }  
    static A build(){    //静态方法要被调用时才被执行,与静态块不一样
        A a =new A();     
        return a;
    }  
} 

 当内部类是非静态的:

 

public class InnerClass {  
    class A{  
        int a = 10;  
        void b(){  
            System.out.println("this is A.b()!");  
        }  
    }     
    public static void main(String[] args) {  
        InnerClass ic = new InnerClass();  
        InnerClass.A aa = ic.new A();  
        aa.b();  
    }  
}  
 3、在内部类的非静态方法中创建外部类的实例。(使用外部类.this来创建外部类的实例)

 

这里为什么内部类能创建外部类?应该和Jvm机制有关,在后面的章节详解

 

public class InnerClass {  
    class A{  
        int a = 10;  
        void build(){  
            InnerClass ic = InnerClass.this;   //这个this是构造方法
            ic.a();  
        }  
    }  
    void a(){  
        System.out.println("this is InnerClass.a()!");  
    }  
}  
 4、在内部类的静态方法中创建外部类的实例。(直接通过new来创建)

 

 

public class InnerClass {  
    static class A{  
        int a = 10;  
        static void build(){  
            InnerClass ic = new InnerClass();  
            ic.a();  
        }  
    }      
    void a(){  
        System.out.println("this is InnerClass.a()!");  
    }  
} 
 5、其他类中创建内部类实例

 

 

class B {  
    class A{  
        void a(){  
            System.out.println("this is A.a()!");  
        }  
    }  
    static class C{  
        void c(){  
            System.out.println("this is C.c()!");  
        }  
    }  
}  
 public class AKL{  
    public static void main(String[] args){  
        /*创建非静态内部类*/  
        B ic = new B();  
        B.A a = ic.new A();  
        a.a();  
          
        /*创建静态内部类*/  
        B.C c = new B.C();  
        c.c();  
    }  
}  
 看个深层嵌套的:

 

 

public class ABC {  
    void a() {  
        System.out.println("this is A.a()!");  
    }  
  
    class B {  
        void b() {  
            System.out.println("this is B.b()!");  
        }  
        class C {  
            void c() {  
                a();  
                b();  
                System.out.println("this is C.c()!");  
            }  
        }  
    }  
    public static void main(String[] args) {  
        ABC abc = new ABC();  
        ABC.B b = abc.new B();  
        ABC.B.C c = b.new C();  
        c.c();  
    }  
}  
 &&:此处最重要的就是这个”.new”操作符。同时,在类C内部调用a()和b()都很轻松,就说明内部类就相当于一个普通的变量,即使是private权限的,也一样直接调用,因为它们在同一个类中。

 

匿名内部类的创建:

 

interface A {  
    void a();  
}  
  
public class InnerClass_NoName {  
    public A test() {   //内部类为接口A的实现类(方法内部类)
        return new A() {  
            public void a() {  
                System.out.println("");  
            }  
        };  
    }  
  
    public static void main(String[] args) {  
        InnerClass_NoName icn = new InnerClass_NoName();  
        A a = icn.test();  
        a.a();    //a可以调用匿名内部类,实现接口方法的向上转型
    }  
}  
 典型的情况是,内部类继承自某个类或实现某个接口,内部类的代码操作创建其的外围类的对象。所以你可以认为内部类提供了某种进入其外围类的窗口。使用内部类最吸引人的原因是:每个内部类都能独立地继承自一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响。如果没有内部类提供的可以继承多个具体的或抽象的类的能力,一些设计与编程问题就很难解决。从这个角度看,内部类使得 多重继承的解决方案变得完整。接口解决了部分问题,而内部类有效地实现了“ 多重继承”。一般情况,内部类不宜过长,否则就会显得头重脚轻。

 

使用匿名内部类应该注意:

a)        匿名内部类不能有构造方法

b)        匿名内部类不能定义任何静态成员、方法和类。

c)         匿名内部类不能是public,protected,private,static。

d)        只能创建匿名内部类的一个实例。

e)        一个匿名内部类一定是在new的后面,用其隐含实现一个接口或实现一个类。

 

f)         因匿名内部类为局部内部类,所以局部内部类的所有限制都对其生效。

 

 

内部类分为成员内部类、静态嵌套类、方法内部类、匿名内部类。
几种内部类的共性:
A、内部类仍然是一个独立的类,在编译之后会内部类会被编译成独立的.class文件,但是前面冠以外部类的类命和$符号。
B、内部类不能用普通的方式访问。内部类是外部类的一个成员,因此内部类可以自由地访问外部类的成员变量,无论是否是private的。

1、成员内部类:形式如下
    class Outer {
        class Inner{}
    }       
编译上述代码会产生两个文件:Outer.class和Outer$Inner.class。
成员内部类内不允许有任何静态声明!下面代码不能通过编译。
    class Inner{
        static int a = 10;
    } 

 从技术上讲,静态嵌套类不属于内部类。因为内部类与外部类共享一种特殊关系,更确切地说是对实例的共享关系。而静态嵌套类则没有上述关系。它只是位置在另一个类的内部,因此也被称为顶级嵌套类。

静态的含义是该内部类可以像其他静态成员一样,没有外部类对象时,也能够访问它。静态嵌套类不能访问外部类的成员和方法。
public class InnerClass {  
    static class A{  
        static int a = 10;  
        static void a(){  
            System.out.println("this is A.a()!");  
        }  
    }  
}  

 接口内部类:

public interface Interface_Class {  
    void say();  
    class IC implements Interface_Class{  
        @Override  
        public void say() {  
            System.out.println("hello");  
        }  
        
    }  
}  

 适合于创建公共代码,供所有实现了该接口的类使用。

内部类的继承,我们说过,内部类持有对外部类的引用,所以,在继承的时候,我们需要初始化这个“隐藏”着的引用,请看下面的代码:

class AAA {  
    class BBB {   
    }  
}  
public class InnerClass_Extends extends AAA.BBB {  
    public InnerClass_Extends(AAA aaa) {  
        aaa.super();  
    }  
    public static void main(String[] args) {  
        AAA aaa = new AAA();  
        InnerClass_Extends ice = new InnerClass_Extends(aaa);  
    }  
} 

 最后,我们总结下使用内部类的原因:每个内部类都能独立继承自一个接口的实现,和外部类没有任何关系(不论外部类是否实现了该接口)。

说的再简单一点就是,内部类是Java多继承机制的完美补充,如果现在非得用抽象类实现多继承,很明显是不可能的,此处就必须使用内部类。

 

铅笔类
public abstract class Pencil {
  public abstract void write();
}
橡皮擦类
public abstract class Eraser {
  public abstract void erase();
} 
带橡皮擦的铅笔类:
public class PencilWithEraser {     
    private MyPencil pencil = new MyPencil();   
    private MyEraser eraser = new MyEraser();   
    private class MyPencil extends Pencil {   
        public void write() {   
            System.out.println("Use to write");   
        }   
    }   
    private class MyEraser extends Eraser {   
        public void erase() {   
            System.out.println("Use to erase");   
        }   
    }   
    public void write() {   
        pencil.write();   
    }   
    public void erase() {   
        eraser.erase();   
  

 

 如果你是高手来群指教:366437263   ,如果你是菜鸟,来我们一起进步。

欢迎继续学习!

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值