亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

(Thinking in Java)第9章 接口

CoorChice / 2095人閱讀

摘要:但如果導(dǎo)出類還有抽象方法,那這個(gè)類還應(yīng)該加上聲明為抽象類。并且接口具有繼承的一系列特點(diǎn),如向上轉(zhuǎn)型等等。接口中的方法是自動(dòng)是的。

Thinking in Java 好書全是干貨 一、抽象類和抽象方法

抽象方法:這種方法只有聲明而沒有方法體,下面是抽象方法生命所采用的語法

abstract void f();

包含抽象方法的類叫做抽象類,如果一個(gè)類包含一個(gè)或多個(gè)抽象方法,該類必須被限定為抽象的,并且編譯器不會(huì)允許直接創(chuàng)建一個(gè)抽象類對(duì)象,正確的做法是從這個(gè)抽象類繼承并為抽象方法完成定義,這樣就可以創(chuàng)建這個(gè)類的對(duì)象。但如果導(dǎo)出類還有抽象方法,那這個(gè)類還應(yīng)該加上abstract聲明為抽象類。簡(jiǎn)單的使用如下

package tij.interfacedemo;

public class Test {
    public static void main(String[] args) {
        new Wind().play(Note.MIDDLE_A);
    }
}
enum Note{
    MIDDLE_A,MIDDLE_B,MIDDLE_C;
}
abstract class Instrument{//抽象父類
    private int i;//
    public abstract void play(Note n);
    public String what(){
        return "Instrument";
    }
    public abstract void adjust();
}
class Wind extends Instrument{
    public void play(Note n){
        System.out.println("Wind.play() "+n);
    }
    public String what(){
        return "wind";
    }
    public void adjust(){
        
    }
}

其實(shí)可以發(fā)現(xiàn)和普通繼承沒什么區(qū)別。

二、接口

接口(interface)是一個(gè)完全抽象的類,沒有任何具體實(shí)現(xiàn)方法,允許創(chuàng)建者創(chuàng)建方法的方法名、參數(shù)列表以及返回類型,但沒有任何方法體。接口體現(xiàn)的思想是:“實(shí)現(xiàn)了這個(gè)接口的類看起來都像這樣”。并且接口具有繼承的一系列特點(diǎn),如向上轉(zhuǎn)型等等。
接口可以加public關(guān)鍵字(如果要加也只能加public,不能加private和protected),不添加就是默認(rèn)訪問權(quán)限(包訪問權(quán)限)。接口中的方法是自動(dòng)是public abstract的。接口也可以包含域(即引用變量或基本變量),并且自動(dòng)是static final的,并且也不能被private和protected修飾。如下例:

package tij.interfacedemo;

public class Test {
    public static void main(String[] args) {
        new Wind().play(Note.MIDDLE_A);
    }
}
enum Note{
    MIDDLE_A,MIDDLE_B,MIDDLE_C;
}
interface Instrument{//
    int i=5;//
    void play(Note n);
    String what();
    void adjust();
}
class Wind implements Instrument{
    public void play(Note n){
        System.out.println("Wind.play() "+n);
    }
    public String what(){
        return "wind";
    }
    public void adjust(){
        
    }
}
三、完全解耦

這是接口的一個(gè)很好的功能
在繼承中,如果一個(gè)方法接受一個(gè)類的實(shí)例作為參數(shù),那么你可以用這個(gè)類或子類的實(shí)例當(dāng)做傳入?yún)?shù),如下例:

package tij.interfacedemo;

import java.util.Arrays;

public class Test {
    static void process(Processor p, Object s) {
        System.out.println("Using Processor:" + p.name());
        System.out.println(p.process(s));
    }

    static String s = "Disagreement with beliefs is by definition incorrect";

    public static void main(String[] args) {
        process(new Upcase(), s);
        process(new Downcase(), s);
        process(new Splitter(), s);
    }
}

class Processor {
    public String name() {
        return getClass().getSimpleName();
    }

    Object process(Object input) {
        return input;
    }
}

class Upcase extends Processor {
    String process(Object input) {
        return ((String) input).toUpperCase();
    }
}

class Downcase extends Processor {
    String process(Object input) {
        return ((String) input).toLowerCase();
    }
}

class Splitter extends Processor {
    String process(Object input) {
        return Arrays.toString(((String) input).split(" "));
    }
}

在本例中,Test.process方法可以接受一個(gè)Processor以及其子類的實(shí)例對(duì)象,然后對(duì)一個(gè)Object的對(duì)象s進(jìn)行操作,根據(jù)傳入的Processor不同,進(jìn)行的操作也不同,這種方法體現(xiàn)了策略設(shè)計(jì)模式,這類方法包含要執(zhí)行的固定部分(s),策略包含變化的部分(p)。但是在這個(gè)例子中要注意兩個(gè)與本章不相關(guān)的事兒:1.應(yīng)該想想為什么子類明明沒有重寫name方法,但輸出卻還是像重寫了一樣。2.子類重寫了process方法,但返回值不是Object而是String,重寫方法必須要是與類方法的返回類型的相同或者是其子類。

但是假如現(xiàn)在我們發(fā)現(xiàn)了一系列濾波器類,如下:

class Waveform{//代表波形
    private static long counter;
    private final long id=counter++;
    public String toString(){
        return "Waveform"+id;
    }
}

class Filter{//濾波器
    public String name(){
        return getClass().getSimpleName();
    }
    public Waveform process(Waveform input){
        return input;
    }
}

class LowPass extends Filter{
    double cutoff;//設(shè)定低通濾波器的濾波上限
    public LowPass(double cutoff){
        this.cutoff=cutoff;
    }
    public Waveform process(Waveform input){
        return input;
    }
}

class HighPass extends Filter{
    double cutoff;//設(shè)置高通濾波器的濾波下限
    public HighPass(double cutoff){
        this.cutoff=cutoff;
    }
    public Waveform process(Waveform input){
        return input;
    }
}
class BandPass extends Filter{
    double lowCutoff,highCutoff;//設(shè)置帶通濾波器的濾波上下限
    public BandPass(double lowCut,double highCut){
        this.lowCutoff=lowCut;
        this.highCutoff=highCut;
    }
    public Waveform process(Waveform input){
        return input;
    }
}

那么如果想把各種濾波器傳給Test.process方法,那這會(huì)被編譯器阻止,因?yàn)閜rocess方法只接受processor類以及子類,那如果希望運(yùn)用了策略設(shè)計(jì)模式的Test.process方法仍能接受濾波器,那么首先就需要把processor改變成接口:

interface Processor {
    String name() ;

    Object process(Object input) ;
}

abstract class StringProcessor implements Processor{
    public String name(){
        return getClass().getSimpleName();
    }
}

class Upcase extends StringProcessor {
    public String process(Object input) {
        return ((String) input).toUpperCase();
    }
}

class Downcase extends StringProcessor {
    public String process(Object input) {
        return ((String) input).toLowerCase();
    }
}

class Splitter extends StringProcessor {
    public String process(Object input) {
        return Arrays.toString(((String) input).split(" "));
    }
}


class Waveform{//代表波形
    private static long counter;
    private final long id=counter++;
    public String toString(){
        return "Waveform"+id;
    }
}

但接下來我們發(fā)現(xiàn),濾波器這個(gè)類是我們找到的,我們并不能對(duì)這么個(gè)類內(nèi)的代碼進(jìn)行修改,如何讓新的Test.process還能接受濾波器呢,于是我們可以采用適配器設(shè)計(jì)模式,代碼如下:

class FilterAdapter implements Processor {
    Filter filter;
    public FilterAdapter(Filter filter) {
        this.filter = filter;
    }
    public String name() {
        return filter.name();
    }
    public Waveform process(Object input) {
        return filter.process((Waveform) input);
    }
}

這樣傳進(jìn)去這個(gè)FilterAdapter適配器就OK了

四、Java中的多重繼承

接口的另一個(gè)重要的功能就是能實(shí)現(xiàn)多重繼承

package tij.interfacedemo;

public class Test {
    public static void main(String[] args) {
        Hero superman=new Hero();
        superman.fight();
        superman.fly();
        superman.swim();
    }
}

class ActionCharacter {
    public void fight() {
        System.out.println("fight");
    }
}
interface CanFight {
    void fight();
}
interface CanSwim {
    void swim();
}
interface CanFly {
    void fly();
}

class Hero extends ActionCharacter implements CanFight, CanSwim, CanFly {
    public void fly() {
        System.out.println("fly");
    }
    public void swim() {
        System.out.println("swim");
    }

}
五、通過繼承來拓展接口

通過繼承可以生成一個(gè)新的接口,以此來對(duì)原來的接口進(jìn)行拓展;還可以通過繼承在新接口中組合多個(gè)接口(玩的真花= =)。如下:

interface Monster {
    void menace();
}
interface DangerousMonster extends Monster {
    void destroy();
}
interface Lethal {
    void kill();
}
class DragonZilla implements DangerousMonster {
    public void menace() {}
    public void destroy() {}
}
interface Vampire extends DangerousMonster, Lethal {
    void drinkBlood();
}
class VeryBadVampire implements Vampire {
    public void destroy() {}
    public void menace() {}
    public void kill() {}
    public void drinkBlood() {}
}

接口之間可以繼承,可以多繼承,可以相互拓展

1.組合接口時(shí)的名字沖突

在實(shí)現(xiàn)多重繼承時(shí),如果不同接口有相同方法怎么辦

interface I1 {
    void f();
}
interface I2 {
    int f(int i);
}
interface I3 {
    int f();
}
class C {
    public int f() {
        return 1;
    }
}
class C2 implements I1, I2 {
    public int f(int i) {
        return 1;
    }
    public void f() {}//重載
}
class C3 extends C implements I2{
    public int f(int i) {//重載
        return 0;
    }
}
class C4 extends C implements I3{
    //可以不必重寫int f()方法,因?yàn)閺腃那里繼承過來了,但C那里的f()必須是public的
}
//class C5 extends C implements I1{
//    //錯(cuò)誤
//}
//interface I4 extends I1,I3{
//    //錯(cuò)誤
//}

因此在設(shè)計(jì)接口的時(shí)候請(qǐng)盡量避免這點(diǎn)

六、適配接口

接口的一種常用的方法就是之前提到的策略設(shè)計(jì)模式,如編寫一個(gè)進(jìn)行某些操作的方法,而這個(gè)方法接收一些接口,就是說如果你的對(duì)象遵循我的接口那就能用。
下面的例子中使用了scanner,這個(gè)類需要接收一個(gè)readable對(duì)象,其中arg用來存儲(chǔ)要輸入的字符串的

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

public class Test {
    public static void main(String[] args) {
        Scanner s = new Scanner(new RandomWords(10));
        while (s.hasNext()) {
            System.out.println(s.next());
        }
    }
}
class RandomWords implements Readable {
    private static Random rand = new Random(47);
    private static final char[] capitals = "ABCDEFGHIGKLMNOPQRST".toCharArray();
    private static final char[] lowers = "ABCDEFGHIGKLMNOPQRST".toLowerCase()
            .toCharArray();
    private static final char[] vowels = "aeiou".toCharArray();
    private int count;
    public RandomWords(int count) {
        this.count = count;
    }
    public int read(CharBuffer arg) throws IOException {
        if (count-- == 0) {
            return -1;
        }
        arg.append(capitals[rand.nextInt(capitals.length)]);
        for (int i = 0; i < 4; i++) {
            arg.append(vowels[rand.nextInt(vowels.length)]);
            arg.append(lowers[rand.nextInt(lowers.length)]);
        }
        arg.append(" ");
        return 10;// Number of characters appended
    }

}

接口的還有一個(gè)功能就是之前我們提到過的適配器設(shè)計(jì)模式,在這里再舉另一個(gè)與scanner相關(guān)的例子。
首先假如我們現(xiàn)在有一個(gè)如下的類:

class RandomDoubles{
    private static Random rand =new Random(47);
    public double next(){
        return rand.nextDouble();
    }
}

希望讓他作為一個(gè)readable傳入給scanner,來生成隨機(jī)的double類型數(shù),這需要裝飾設(shè)計(jì)模式

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

public class Test {
    public static void main(String[] args) {
        Scanner s=new Scanner(new AdaptedRandomDoubles(7));
        while(s.hasNext()){
            System.out.println(s.next());
        }
    }
}
class AdaptedRandomDoubles extends RandomDoubles implements Readable {
    private int count;
    public AdaptedRandomDoubles(int count){
        this.count=count;
    }
    public int read(CharBuffer cb) throws IOException {
        if(count--==0){
            return -1;
        }
        String result=Double.toString(this.next());
        cb.append(result);
        return result.length();
    }

}
七、接口中的域

實(shí)例變量都是static final的,好了結(jié)束

八、嵌套接口

推薦先看完內(nèi)部類再來看這個(gè)

1.類中的接口
class t1 implements A.C,A.B{//訪問不到A.D
    public void f() {
    }
}

class A {
    interface B {
        void f();
    }
    public class BImp implements B {
        public void f() {}
    }
    private class BImp2 implements B {
        public void f() {}
    }

    public interface C {
        void f();
    }
    class CImp implements C {
        public void f() {}
    }

    private interface D {
        void f();
    }
    private class DImp implements D {
        public void f() {}
    }
    public class DImp2 implements D {
        public void f() {}
    }
}
2.接口中的接口
interface E{
    interface G{
        //默認(rèn)為public
        void f();
    }
}
class t2 implements E.G{
    public void f() {
    }
}
九、接口與工廠

接口時(shí)實(shí)現(xiàn)多重繼承的途徑,而生成遵循某個(gè)接口的對(duì)象的典型方式就是工廠方法設(shè)計(jì)模式

package tij.interfacedemo;
public class Test {
    public static void main(String[] args) {
        Factories.serviceConsumer(new Implementation1Factory());
        Factories.serviceConsumer(new Implementation2Factory());
    }
}

interface Service {
    void method1();
    void method2();
}
interface ServiceFactory {
    Service getService();
}
class Implementation1 implements Service {
    Implementation1() {}
    public void method1() {System.out.println("Implementation1 method1");}
    public void method2() {System.out.println("Implementation1 method2");}
}
class Implementation1Factory implements ServiceFactory {
    public Service getService() {
        return new Implementation1();
    }
}
class Implementation2 implements Service {
    Implementation2() {}
    public void method1() {System.out.println("Implementation2 method1");}
    public void method2() {System.out.println("Implementation2 method2");}
}
class Implementation2Factory implements ServiceFactory {
    public Service getService() {
        return new Implementation1();
    }
}
class Factories{
    static void serviceConsumer(ServiceFactory fact){
        Service s = fact.getService();
        s.method1();
        s.method2();
    }
}

這樣設(shè)計(jì)的好處就是將方法的實(shí)現(xiàn)實(shí)例對(duì)象的生成分離開來,而且在使用Factories.serviceConsumer的時(shí)候不需要特定指定是哪種Service.

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/67585.html

相關(guān)文章

  • Thinking in Java11 持有對(duì)象

    摘要:迭代器解決了這個(gè)問題。刪除后于是我們可以寫一個(gè)方法,接受一個(gè)類型,然后讓他調(diào)用方法,這就不需要考慮這個(gè)是個(gè)還是了,也就是說,可以將遍歷容器的操作與序列底層的結(jié)構(gòu)分離,迭代器統(tǒng)一了對(duì)容器類的訪問方式。十二和兩種遍歷的方法,與迭代器方法。 一、泛型和類型安全的容器 package tij.hoding; import java.util.ArrayList; public class ...

    v1 評(píng)論0 收藏0
  • Thinking in Java14 類型信息

    摘要:通過運(yùn)行時(shí)類型信息,程序能夠使用基類的指針或引用來檢查這些指針或引用所指的對(duì)象的實(shí)際派生類型。編程應(yīng)該盡量面向接口編程,應(yīng)該對(duì)類型信息盡量的少了解二對(duì)象看書,書上寫得好靜態(tài)語句塊在這個(gè)類被加載的時(shí)候運(yùn)行。 一、為什么需要RTTI Run-Time Type Information。通過運(yùn)行時(shí)類型信息,程序能夠使用基類的指針或引用來檢查這些指針或引用所指的對(duì)象的實(shí)際派生類型。編程應(yīng)該盡量...

    tomorrowwu 評(píng)論0 收藏0
  • Thinking in Java10 內(nèi)部類

    摘要:內(nèi)部類中也可以取得這個(gè)外部類對(duì)象引用。創(chuàng)建成員內(nèi)部類對(duì)象的時(shí)候需要外部類對(duì)象。另外在方法中的內(nèi)部類不能加等權(quán)限修飾符,只能加和修飾符。可以在接口內(nèi)部定義內(nèi)部類,而且他們即使沒有修飾,也會(huì)自動(dòng)變成的。 Thinking in Java撈干貨,寫筆記 一、成員內(nèi)部類 1.最基本使用 public class Demo { class Contents{ privat...

    Brenner 評(píng)論0 收藏0
  • Thinking in Java15 泛型

    摘要:反省發(fā)放需要將泛型參數(shù)列表之余返回值之前杠桿利用類型參數(shù)推斷現(xiàn)在可以了,別。現(xiàn)在可以顯式的類型說明這段代碼沒毛病的,可變參數(shù)與泛型方法沒啥好說用于的泛型方法方法可以透明的應(yīng)用于實(shí)現(xiàn)了泛型接口的類。但是這個(gè)卻可以指向各種是的對(duì)象。 二、簡(jiǎn)單泛型 2.一個(gè)堆棧類 package tij.generic; public class Test { public static void...

    tinyq 評(píng)論0 收藏0
  • Thinking in Java13 字符串

    摘要:四上的操作看五格式化輸出運(yùn)用和語言很相似和是等價(jià)的喲類格式化說明符轉(zhuǎn)換六正則表達(dá)式網(wǎng)上教程學(xué)七掃描輸入新增了類。 一、不可變String String類型的對(duì)象是不可變的,所有的改變實(shí)際上都是創(chuàng)建了一個(gè)新的String對(duì)象,另外當(dāng)String作為傳入?yún)?shù)的時(shí)候,其實(shí)實(shí)際上傳入的是這個(gè)引用的一個(gè)拷貝,這個(gè)方法結(jié)束了之后這個(gè)傳入的引用也就消失了,原來的那個(gè)String不會(huì)受到方法內(nèi)的影響而...

    feng409 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<