java 抽象类与接口

http://www.cnblogs.com/wenruo/p/5366052.html

抽象类

当基类比较抽象的时候一些函数就无法实现。比如动物类,你可以知道猫如何叫狗如何叫,但你无法说清动物如何叫,于是对于比较抽象的基类,其中的一些方法可以只声明,不实现。这样的方法叫做抽象方法,含有抽象方法的类叫做抽象类。抽象方法和抽象类需要用关键字abstract来标识。

含有抽象方法的类的对象是不安全的,因此java中不允许创建抽象类的对象。

对于一个不含有抽象方法的类也可以设为抽象类,这样,就能限制这个类不能产生对象了。

接口

当一个类足够抽象,将不会实现任何方法。接口(interface)是一个完全抽象的类,不提供任何具体实现。

接口同类一样有public和默认(包)访问权限。

接口中的域默认是static和final的

接口中的方法默认是public的,所以继承的时候注意实现的时候要声明为public。

接口的用处和抽象类看起来并不相同。比如上面说的抽象基类动物类,动物会叫,继承类包括猫狗。但是汽车,电视都会“叫”,却并不合适继承,这时一个“声音”接口就比较合适。

 

接口的多重继承

Because an interface has no implementation at all—that is, there is no storage associated with an interface—there’s nothing to prevent many interfaces from being combined.

一个类可以实现多个接口,却只能继承一个类。接口可以继承多个接口。

1、一个类实现两个接口而两个接口的存在完全相同的方法时,实现一个就可以了。

interface A { void f(); }
interface B { void f(); }

class C implements A, B {
    @Override
    public void f() {
        System.out.println("f()");
    }    
}

public class Test {
    public static void main(String[] args) {
        new C().f();
    }
}

 

2、如果两个方法名字相同参数列表不同,会实现重载。

interface A { void f(int x); }
interface B { void f(); }

class C implements A, B {
    @Override
    public void f() {
        System.out.println("f()");
    }
    @Override
    public void f(int x) {
        System.out.println("f(" + x + ")");
    }    
}

public class Test {
    public static void main(String[] args) {
        C c = new C();
        c.f(); c.f(1);
    }
}

 

3、如果参数列表相同,返回值不同,将会报错。

 

4、实现接口的方法也可以是继承自父类

interface A { void f(); }
interface B { void f(); }

class C {
    public void f() {
        System.out.println("f()");
    }
}

class D extends C implements A, B {
}

public class Test {
    public static void main(String[] args) {
        D d = new D();
        d.f();
    }
}

 

 也就是对于一个实现接口的类,只要类中有接口所有函数的实现就可以。

但是注意,未通过implements实现接口,只有相同函数没有用的。

 

interface A { void f(); }
class B {
    public void f(){};
}
public class Test {
    public static void main(String[] args) {
        //A a = new B(); <-- Type mismatch: cannot convert from B to A
    }
}

 

C++中存在菱形继承的问题。

class A{};

class B:public A{};

class C:public A{};

class D:public B,public C();

这样会出现一些问题,因为D中有两个A,因此调用A内的成员是编译器会分不清是哪个。【记得大概是这样吧。。C++无能。。。

 java虽然不存在类的多重继承,但是存在接口多重继承。考虑下面的代码

interface F { void f(); }
interface S1 extends F { void s1(); }
interface S2 extends F { void s2(); }
interface T extends S1, S2 { void t(); }

class Fo implements T {
    public void f() { System.out.println("f"); }
    public void s1() { System.out.println("s1"); }
    public void s2() { System.out.println("s2"); }
    public void t() { System.out.println("t"); }    
}

public class Diamond {
    public static void main(String[] args) {
        Fo fo = new Fo(); fo.f();
    }
}

其实由上面的讨论也可以想到这完全不会有问题。因为java的接口根本不提供具体实现。这也是Java设计单一继承和接口的原因。

 

 接口中的域

定义时即要初始化,可以是被非常量的表达式初始化。

interface F {
    int i = 0;//int i; <- error
    int j = i;
    int k = j * 10;
    void f(); 
}

这些域不是接口的一部分,它们的值被存储在该接口的静态存储区域内。

 

配适器设计模式

某个现有的类的接口和需求不同,可以通过实现某个接口达到要求。(因为《thinking in java》提到所以稍微看了一下。。理解浅显。。

一般都是用插头举例,如果插头型号不合适就在外面在套一个转换插头实现工作。(原谅我是在写不出符合逻辑的例子。。。。。

class A {
    public void solveByA() {}
}
interface B {
    public void solveByB();
}
class C {
    public static void solve(B b) {
        b.solveByB();
    }
}
/* 想要在solve中调用A明显是不行的,于是加一个配适器给A,让它套一个B的外壳   */
class AImplementsB extends A implements B {
    @Override
    public void solveByB() {
        solveByA();
    }
}
/* 由此可以想到对于所有的类  只要我们能对它实现接口B 就可以使该类作用于solve 提高了复用性 */
public class AdapterDemo {
    public static void main(String[] args) {
        C.solve(new AImplementsB());
    }
}

 

举个实际的用处。Scanner的构造器接受的是一个Readable接口,也就是说只要一个类实现了Readable接口,就可以使Scanner作用于它。

Readable接口中只有一个方法public int read(CharBuffer arg0);在read内部将输入内容添加到CharBuffer参数中,返回添加或者没有输入返回-1。

import java.nio.CharBuffer;
import java.util.Random;
import java.util.Scanner;

public class RandomWords implements Readable {
    private static Random rand = new Random();
    private static final char[] capitals = 
            "QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm".toCharArray();
    private int count = 0;
    public RandomWords(int count) {
        this.count = count;
    }
    @Override
    public int read(CharBuffer cb) {
        if (count-- == 0) return -1;
        cb.append(capitals[rand.nextInt(capitals.length)]);
        cb.append(" ");
        return 1;
    }
    public static void main(String[] args) {
        Scanner in = new Scanner(new RandomWords(10));
        while (in.hasNext()) {
            System.out.print(in.next() + ",");
        }
        in.close();
    }
}

 

接口可以嵌套在其他类或接口中。

private 或 public 或 默认访问权限 都可以。

没弄明白什么用ing。

posted @ 2016-04-07 23:07  我不吃饼干呀  阅读(358)  评论(0编辑  收藏  举报