day05

续 接口

9.2 接口

  1. Interface关键字使抽象的概念更向前迈进了一步.abstract关键字允许人们在类中创建一个或多个没有任何定义的方法--提供了接口部分,但是没有提供任何相应的具体实现,这些实现是由类的继承者创建的.

Interface这个关键字产生了一个完全抽象的类,他根本就没有提供任何具体实现.他允许创建者确定方法名 参数列表和返回类型,但是没有任何方法体.接口只提供了形式,而未提供任何具体实现.

  1. interface不仅仅是一个极度抽象的类,因为它允许人们通过创建一个能够被向上转型为多种基类的类型,来实现某种类似多重继变种的特性.
  2. 就像类一样,可以在interface关键字前面添加public关键字,如果不添加public关机找你,则它只有包访问权限,这样它就只能在同一个包内可用.接口也可以包含域,但是这些域隐式地是static和final的.
  3. 可以选择在接口中显式地方法声明为public的,但即使你不这么做,他们也是public的.

9.3完全耦合

  1. 用代码来解释一下耦合关系(刚开始没有看懂第二天又看才看懂)
//看两点
//1. class Processor   而不是  interface Processor(现象:完全耦合.造成应用领域太小)
//2. //如果Process是一个接口,那么这些限制就会变得松动,是的你可以复用结构该接口的Apply.process().

class Processor{//public interface Processor{String name(); Object process(Object input);}
    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){
        // The split() argument divides a String into pieces;
        return Arrays.toString(((String)input).split(" "));
    }
}




//现在我们发现了一组电子滤波器  看起来是和上面的差不多,但是我们不能够取用主方法里面的Apply.process()方法  
//那么通过下面的代码就可以看出来   这样写代码的复用性太差.

public class Waveform {
    private static long counter;
    private final long id = counter++;
    public String toString(){
        return "Waveform "+ id;
    }
}
public class Filter {
    public String name(){
        return getClass().getSimpleName();
    }
    public Waveform process(Waveform input){
        return input;
    }
}
public class LowPass extends Filter {
    double cutoff;
    public LowPass(double cutoff){
        this.cutoff = cutoff;
    }
    public Waveform process(Waveform input){
        return input;//Dummy processing
    }
}
public class HighPass extends Filter {
    double cutoff;
    public HighPass(double cutoff){
        this.cutoff = cutoff;
    }
    public Waveform process(Waveform input){
        return input;
    }
}
public class BandPass extends Filter {
    double lowCutoff,highCutoff;
    public BandPass(double lowCut,double highCut){
        lowCutoff = lowCut;
        highCutoff = highCut;
    }
    public Waveform Process(Waveform input){
        return input;
    }
}

//这样,创建一个能够根据所传递的参数对象的不同而具有不同行为的方法,被称为策略设计模式
public class Apply {
    public static void process (Processor p,Object s){
        print("Using Processor " + p.name());
        print(p.process(s));
    }
    public 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);
    }
}

  1. 解耦 适配器模式
class FilterAdapter implements Process{
    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);
    }
}
public class FilterProcess{
    public static void main(String[] args){
        Waveform w = new Waveform();
        Apply.process(new FilterAdapter(new LowPass(1.0)),w);
        Apply.process(new FilterAdapter(new HighPass(2.0)),w);
        Apply.process(new FilterAdapter(new BandPass(3.0,4.0)),w);
    }
}

9.4Java中的多重继承

  1. 注意一点implements关键字之后,可以继承多个接口,并可以向上转型为每个接口.

9.5通过继承来扩展接口

interface Monster{
    void mence();
}
interface DangeousMonster extends Monster{
    void destroy();
}

9.7接口中的域

  1. 接口中的域隐式地是static和final的

9.9接口与工厂(难点与重点)可以说是必知必会的东西

  1. 文字描述:接口时实现多重继承的途径,而生成遵循某个接口的对象的典型方式就是工厂方法设计模式.
  2. 这与直接调用构造器不同,我们在工厂对象上调用的是创建方法,而该工厂对象将生成接口的某个实现的对象.理论上,通过这种方式,我们的代码将完全与接口的实现分离,这就使得我们可以透明地将某个实现替换为另一个实现.
package cn.itcast.zhuofai730.demo9_9;

import java.util.ServiceConfigurationError;

import static cn.itcast.zhuofai730.util.Print.print;

interface Service{
    void method1();
    void method2();
}
interface ServiceFactory{
    Service getService();
}
class Implementation1 implements Service{
    Implementation1(){}//Package access
    public void method1(){print("Implementation1 method1");}
    public void method2(){
        print("Implementation method2");
    }
}
class Implementation1Factory implements ServiceFactory{
    public Service getService(){
        return new Implementation1();
    }
}
class Implementation2 implements Service{
    Implementation2(){}//Pakage access

    @Override
    public void method1() {
        print("Implementation2 method1");

    }

    @Override
    public void method2() {
        print("Implementation2 method2");
    }
}
class Implementation2Factory implements ServiceFactory{
    public Service getService(){
        return new Implementation2();
    }
}
public class Factories {
    public static void serviceConsumer(ServiceFactory fact){
        Service s = fact.getService();
        s.method1();
        s.method2();
    }

    public static void main(String[] args) {
        serviceConsumer(new Implementation1Factory());
        //Implementations are completely interchangeable;
        serviceConsumer(new Implementation2Factory());
    }
}

number two program

package cn.itcast.zhuofai730.demo9_9;


import static cn.itcast.zhuofai730.util.Print.print;

interface Game{boolean move();}
interface GameFactory {Game getGame();}
class Checkers implements Game{
    private int moves = 0;
    private static final int MOVES = 3;
    public boolean move(){
        print("Checker move" + moves);
        return ++moves != MOVES;
    }
}
class CheckersFactory implements GameFactory{
    public Game getGame(){
        return new Checkers();
    }
}
class Chess implements Game{
    private int moves = 0;
    private static final int MOVES = 4;
    public boolean move(){
        print("Chess move "+ moves);
        return ++moves != MOVES;
    }
}
class ChessFactory implements GameFactory{
    public Game getGame(){
        return new Chess();
    }
}

public class Games {
    public static void playGame(GameFactory factory){
        Game s = factory.getGame();
        while(s.move())
            ;
    }
    public static void main(String[] args) {
        playGame(new CheckersFactory());
        playGame(new ChessFactory());
    }
}

内部类

可以将一个类的定义放在另一个类的定义内部,这就是内部类

内部类是一种非常有用的特性,因为他允许你把一些逻辑相关的泪组织在一起,并控制位于内部的类的可视性,然而必须要了解,内部类与组合是完全不同的概念,这一点很重要.

10.1创建内部类

  1. 如果想从外从外部类的非静态方法之外的任意位置创建某个内部类的对象,那么必须像在main()方法中那样,具体指明这个对象的类型:OuterClassName.InnerClassName.

10.2链接到外部类

  1. 当生成一个内部类对象时,此对象与制造它的外围对象(enclosing object)之间就有了一种联系,使用它能访问其外围对象的所有成员,而不需要任何条件.
  2. 当外部类的对象创建了一个内部类对象时,此内部类对象必定会秘密地捕获一个指向那个外围类对象的引用.然后你在访问此外围类的成员时,就是用那个引用来选择外围类的成员.
//这个例子可以和10.3一起来看
//利用外部方法来创建内部类对象
//Selector selector = sequence.selector();
//相当于this.newSequenceSelector();
interface Selector{
}
public class Sequence {
    public void add(Object x){}
    private class SequenceSelector implements Selector{}
    public Selector selector(){
        return new SequenceSelector();
    }
    public static void main(String[] args){
        Sequence sequence = new Sequence(10);
        Selector selector = sequence.selector();
    }
}

10.3使用.this与.new

内部类就像一个方法一样用外部类"."外部类调用

  1. 如果你需要生成对外部类对象的引用,可以使用外部类的名字后面紧跟圆点和this.
//DotThis.this;返回一个外部类的引用,前面讲了
//>当外部类的对象创建了一个内部类对象时,此内部类对象必定会秘密地捕获一个指向那个外围类对象的引用.
//所以利用DotThis.this可以获取DotThis对象

public class DotThis {
    void f(){
        System.out.println("DoThis.f()");
    }
    public class Inner{
        public DotThis outer(){
            return DotThis.this;
        }
    }
    public Inner inner(){
        return new Inner();
    }
    public static void main(String[] args) {
        DotThis dt = new DotThis();
        DotThis.Inner dti = dt.inner();
        dti.outer().f();
    }
}
  1. 创建其某个内部类的对象.实现此目的,你必须在new表达式中提供对其他外部类对象的引用,这是需要使用.new语法.
public class DotNew {
    public class Inner{}

    public static void main(String[] args) {
        DotNew dn = new DotNew();
        DotNew.Inner dni = dn.new Inner();
    }
}
  1. 在拥有外部类对象之前是不可能创建内部类对象的.这是因为内部类对象会暗暗地连接到创建它的外部类对象上.但是,如果你创建的是嵌套类(静态内部类),那么它就不需要对外部类对象的引用.

10.4内部类与向上转型

  1. 当将内部类向上转型为其基类,尤其是转型为一个接口的时候,内部类就有了用武之地(从实现了某个接口的对象,得到对此接口的引用,与向上转型为这个对象的基类,实质上效果是一样的.)这是因为此内部类--某个接口的实现--能够完全不可见,并且不可用.所得到的知识指向基类或接口的引用,使用能够很方便地隐藏实现细节.
public interface Contents {
    int value();
}
public interface Destination {
    String readLabel();
}
class Parcel4{
    private class PContents implements Contents{
        private int i = 11;
        @Override
        public int value() {
            return i;
        }
    }
    protected class PDestination implements Destination{
        private String label;
        private PDestination(String whereTo){
            label = whereTo;
        }
        public String readLabel(){
            return label;
        }
    }
    public Destination destination(String s){
        return new PDestination(s);
    }
    public Contents contents(){
        return new PContents();
    }
}
public class TestParcel {
    public static void main(String[] args) {
        Parcel4 p = new Parcel4();
        Contents c = p.contents();
        Destination d = p.destination("Tasmania");
    }
}

10.5 在方法和作用域内的内部类

  1. 声明定义内部类的两个理由
    1. 你实现了某类型的接口,于是可以创建并返回对其的引用.
    2. 你要解决一个复杂的问题,想创建一个类来辅助你的解决方案,但是又不希望这个类时公共可用的.
  2. 定义类的方式
    1. 一个定义在方法中的类
    2. 一个定义在作用域内的类,此作用域在方法的内部.
    3. 一个实现了接口的匿名类
    4. 一个匿名类,它扩展了有非默认构造器的类
    5. 一个匿名类,他执行字段初始化
    6. 一个匿名类,它通过实例初始化实现构造(匿名类不可能有构造器)

10.6匿名内部类

//两个知识点
//1. 如果基类需要一个有参数的构造器,只需要简单地传递合适的参数给基类的构造器即可
//2. 尽管Wrapping只是一个具有具体实现的普通类,但它还是被其导出类当作公共"接口"来使用
public class Wrapping {
    private int i;
    public Wrapping(int x){
        i = x;
    }
    public int value(){
        return i;
    }
}
public class Parcel8 {
    public Wrapping wrapping(int x){
        return new Wrapping(x){
            public int value(){
                return super.value() * 47;
            }
        };
    }

    public static void main(String[] args) {
        Parcel8 p = new Parcel8();
        Wrapping w = p.wrapping(10);
    }
}
  1. 如果定义一个匿名内部类,并且希望它使用一个在他其他外部定义的对象,那么编译器会要求其参数引用是final的.

10.7嵌套类

  1. 如果不需要内部类对象与外围类对象之间有联系,那么可以将内部类声明为static.
  2. 理解static应用于内部类时的含义,就必须记住,普通的内部类对象隐式地保存了一个引用,指向创建它的外围类对象.然而,当内部类时static时,就不是这样了.
  3. 嵌套类意味着:
    1. 要创建嵌套类的对象,并不需要其外围类的对象.
    2. 不能从嵌套类的对象中访问非静态的外围类对象.
  4. 嵌套类与普通的内部类还有一个区别.普通内部类的字段与方法,只能放在累的外部层次上,所以普通的内部类不能有static数据和static字段,也不能包含嵌套类.但是嵌套类可以包含所有东西.
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,463评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,868评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,213评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,666评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,759评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,725评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,716评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,484评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,928评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,233评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,393评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,073评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,718评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,308评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,538评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,338评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,260评论 2 352

推荐阅读更多精彩内容