9.1 抽象类和抽象方法

抽象方法 abstract void f(); 抽象方法没有body
抽象类abstract class 类名{}

抽象类不一定有 抽象方法
有抽象方法的类 一定是 抽象类 或接口

抽象类不能实例化
按照多态方式,由具体的子类实例化

抽象类的子类 要么是抽象类,要么重写抽象类中所有抽象方法。

package chapter9interfaces.music4;

import chapter8polymorphism.music.Note;

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 {

    @Override
    public void play(Note n) {
        System.out.println("Wind.play()" + n);
    }

    public String what() {
        return "Wind";
    }

    @Override
    public void adjust() {

    }
}

class Percussion extends Instrument { // 打击乐器

    @Override
    public void play(Note n) {
        System.out.println("Percussion.play()" + n);
    }

    public String what() {
        return "Percussion";
    }

    @Override
    public void adjust() {
    }
}

class Stringed extends Instrument { // 有弦(乐器)

    @Override
    public void play(Note n) {
        System.out.println("Stringed.play()" + n);
    }

    public String what() {
        return "Stringed";
    }

    @Override
    public void adjust() {
    }
}

class Brass extends Wind { // 铜管乐器

    @Override
    public void play(Note n) {
        System.out.println("Brass.play()" + n);
    }

    @Override
    public void adjust() {
        System.out.println("Brass.adjust()");
    }
}

class Woodwind extends Wind{
    @Override
    public void play(Note n) {
        System.out.println("Woodwind.play()" + n);
    }

    public String what() {
        return "Woodwind";
    }
}
public class music4 {
    static void tune(Instrument i){
        i.play(Note.MIDDLE_C);
    }
    static void tuneAll(Instrument[] e){
        for(Instrument i: e)
            tune(i);
    }

    public static void main(String[] args) {
        Instrument[] orchestra = { // 管弦乐队 加入数组时 向上转型
                new Wind(),
                new Percussion(),
                new Stringed(),
                new Brass(),
                new Woodwind(),
        };
        tuneAll(orchestra);
    }
} /* Output
Wind.play()MIDDLE_C
Percussion.play()MIDDLE_C
Stringed.play()MIDDLE_C
Brass.play()MIDDLE_C
Woodwind.play()MIDDLE_C
*/

abstract class NoMethod{
}
public class E02_abstract {
    public static void main(String[] args) {
//        NoMethod noMethod = new NoMethod(); //抽象类不能创建实例
    }
}


abstract class ContainPrint {
    abstract void print();

    ContainPrint() {
        print();
        System.out.println("ContainPrint constructor");
    }
}

class SubClass extends ContainPrint {
    int a = 5;

    @Override
    void print() {
        System.out.println(" a = " + a);
    }
}

public class E03 {
    public static void main(String[] args) {
        SubClass subClass = new SubClass();
        subClass.print();
    }
}
/* Output
 a = 0  在初始化之前,jvm 分配存储对象 为 a 默认值 置0 。在运行子类初始化前,调用基类的构造器 ,所以能看到 a 为0
ContainPrint constructor  构造器内调用依赖于子类初始化的方法是危险的。
 a = 5
 */
package chapter9interfaces.music4;

abstract class NoMethod {

}

abstract class WithMethods {
    abstract public void f();
}

class Extended1 extends NoMethod {
    public void f() {
        System.out.println("Extended1.f()");
    }
}

class Extended2 extends WithMethods {
    public void f() {
        System.out.println("Extended2.f()");
    }
}

public class E04 {
    public static void test1(NoMethod nm) {  //需要向下转型
        ((Extended1) nm).f();
    }

    public static void test2(WithMethods wm) { // 因为f()在基类中已经定义,所以不需要向下转型
        wm.f();
    }

    public static void main(String[] args) {
        NoMethod e04_noMethod = new Extended1();
        test1(e04_noMethod);

        WithMethods withMethods = new Extended2();
        test2(withMethods);

    }
}

与哪些关键字不能共存

// public static abstract void method(); 类名.抽象方法 没有意义
// public final abstract void method(); 强制子类重写 final 不让子类重写,矛盾
// private abstract void method(); private 私有

9.2 接口

完全抽象的类,没有任何具体实现
方法名,参数列表,返回类型

接口成员特点:
成员变量:常量,隐式 是public static 和final
构造方法:接口中没有构造方法 一个类不写继承任何类,默认继承Object
成员方法:只能是抽象方法。默认修饰符 public abstract

接口中所有方法默认是public

类与类:继承关系,只能单继承,可以多层继承
类与接口:实现关系,可以单实现,可以多实现;可以在继承一个类多同时实现多个接口
接口与接口: 继承关系,可以单继承,可以多继承

9.3完全耦合

这部分需要重点,再看 + 练习题11 (后续用单例模式改作业),涉及策略模式,适配器模式
https://www.cnblogs.com/ITPower/p/8550627.html

9.4Java的多重继承

package chapter9interfaces;

interface CanFight {
    void fight();
}

interface CanSwim {
    void swim();
}

interface CanFly {
    void fly();
}

interface CanClimb {
    void climb();
}

class ActionCharacter {
    public void fight() {
        System.out.println("fight");
    }
}

class Hero extends ActionCharacter implements CanFight, CanFly, CanSwim, CanClimb {

    @Override
    public void swim() {
        System.out.println("swim");
    }

    @Override
    public void fly() {
        System.out.println("fly");

    }

    @Override
    public void climb() {
        System.out.println("climb");

    }
}

public class Adventure {
    public static void t(CanFight x) {
        x.fight();
    } //接口做参数

    public static void u(CanSwim x) {
        x.swim();
    }

    public static void v(CanFly x) {
        x.fly();
    }

    public static void x(CanClimb x) {
        x.climb();
    }

    public static void w(ActionCharacter x) {
        x.fight();
    } // 类做参数

    public static void main(String[] args) {
        Hero hero = new Hero();
        t(hero); // 向上转型
        u(hero);
        v(hero);
        w(hero);
        x(hero);
    }
}

多重继承 菱形问题

Java allows multiple interface inheritance but not multiple implementation inheritance
Java允许多接口继承,但不允许多个实现

package chapter9interfaces;

interface BaseInterface {
    void f();
}

interface IntermediateInterface1 extends BaseInterface {
}

interface IntermediateInterface2 extends BaseInterface {
}

interface CombinedInterface extends IntermediateInterface1, IntermediateInterface2 {

}

class CombinedImpl implements CombinedInterface {

    @Override
    public void f() {
        System.out.println("CombinedImpl.f()");
    }
}

public class E13_Diamond {
    public static void main(String[] args) {
        new CombinedImpl().f();

    }
}

9.5通过继承来扩展接口

extends 单一类,多基类接口

9.5.1组合接口时的名字冲突

重载方法仅通过返回类型是区分不开的
在打算组合的不同接口中,尽量使用不同的方法名,否则可能导致混乱

package chapter9interfaces;

interface I1 { void f();}

interface I2 {void f(int i);}

interface I3 {int f();}

class C {
    public int f() {
        return 1;
    }
}

class C2 implements I1, I2 {

    @Override
    public void f() {
    }

    @Override
    public void f(int i) {
    }
}

class C3 extends C implements I2 {
    @Override
    public void f(int i) {
    }
}

class C4 extends C implements I3 {

}

//class C5 extends C implements I1 { //Error:(39, 1) java: 类型chapter9interfaces.I3和chapter9interfaces.I1不兼容; 两者都定义了f(), 但却带有不相关的返回类型
//}

//interface I4 extends I1, I3 { //Error:(39, 1) java: 类型chapter9interfaces.I3和chapter9interfaces.I1不兼容; 两者都定义了f(), 但却带有不相关的返回类型
//
//}

public class InterfaceCollision {
    public static void main(String[] args) {

    }
}

9.6适配接口

package chapter9interfaces;

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

public class RandomWords implements Readable {  // 实现 Readable 接口
    private  static Random rand  = new Random(47);
    private static final char[] capitals = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
    private static final char[] lowers = "abcdefghijklmnopqrstuvwxyz".toCharArray();
    private static final char[] vowels = "aeiou".toCharArray(); // 元音
    private int count;
    
    public RandomWords(int count){this.count = count;}
    @Override
    public int read(CharBuffer cb) throws IOException { // public int read(java.nio.CharBuffer cb) throws IOException;
        if (count-- ==0)
            return -1;
        cb.append(capitals[rand.nextInt(capitals.length)]);
        for(int i =0;i<4;i++){
            cb.append(vowels[rand.nextInt(vowels.length)]);
            cb.append(lowers[rand.nextInt(lowers.length)]);

        }
         cb.append(" "); //空白是默认界定符
        return 10; //字符添加的数量
    }

    public static void main(String[] args) {
        Scanner s = new Scanner(new RandomWords(10)); //  public Scanner(Readable source) 
        while (s.hasNext())
            System.out.println(s.next());
    }
}
package chapter9interfaces;

import java.util.Random;

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

    public static void main(String[] args) {
        RandomDoubles rd = new RandomDoubles();
        for (int i = 0;i < 7;i++){
            System.out.print(rd.next() + " ");
        }
    }
}

package chapter9interfaces;

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

public class AdaptedRandomDoubles extends RandomDoubles implements Readable{
    private int count;

    AdaptedRandomDoubles(int count){this.count = count;}

    @Override
    public int read(CharBuffer cb) throws IOException {
        if (count-- == 0)
            return -1;
        String result = Double.toString(next()) + " ";
        cb.append(result);
        return result.length();
    }

    public static void main(String[] args) {
        Scanner s = new Scanner(new AdaptedRandomDoubles(8));
        while (s.hasNextDouble())
            System.out.println(s.nextDouble() + " ");
    }
}

package chapter9interfaces;

import java.util.Random;

public class RandomChar {
    private static Random rand = new Random(47);
    private static final char[] lowers = "abcdefghijklmnopqrstuvwxyz".toCharArray();
    private static final char[] capitals = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
    private static final char[] vowels = "aeiou".toCharArray();

    char[] generate() {
        char[] buffer = new char[10];
        int index = 0;
        buffer[index++] = capitals[rand.nextInt(capitals.length)];
        for (int i = 0; i < 4; i++) {
            buffer[index++] = lowers[rand.nextInt(lowers.length)];
            buffer[index++] = vowels[rand.nextInt(vowels.length)];
        }
        buffer[index++] = ' ';
        return buffer;
    }
}

package chapter9interfaces;

import chapter9interfaces.RandomChar;

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

public class AdaptedRandomChar extends RandomChar implements Readable {
    private int count;
    AdaptedRandomChar(int count){this.count = count;}

    @Override
    public int read(CharBuffer cb) throws IOException {
        if (count-- == 0)
            return -1;
        char[] result = generate();
        cb.put(result);
        return result.length;
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(new AdaptedRandomChar(10));
        while (scanner.hasNext())
            System.out.println(scanner.next());
    }
}

9.7接口中的域

接口中字段 自动是static final

public interface Months { // static final 常量初始化 大写
    int JANUARY = 1, FEBRUARY = 2, MARCH = 3,
            APRIl = 4, MAY = 5, JUNE = 6,
            JULY = 7, AUGUST = 8, SEPTEMBER = 9,
            OCTOBER = 10, NOVEMBER = 11, DECEMBER = 12;
}

package chapter9interfaces;

public class ExtendMonths implements Months {
    public static void main(String[] args) {
//        MAY =3;  // Compile-time error: cannot assign a value to final variable RED:
        System.out.println(ExtendMonths.MAY);
    }
}

9.7.1初始化接口中的域

不能空final,非常量表达式初始化
static 第一次加载时初始化,这些字段不是接口的一部分,存储在接口的静态存储区域
public interface RandVals {
    Random RAND = new Random(47);
    int RANDOM_INT = RAND.nextInt(10);
    long RANDOM_LONG = RAND.nextLong() * 10;
    float RANDOM_FLOAT = RAND.nextLong() * 10;
    double RANDOM_DOUBLE = RAND.nextDouble() * 10;
}

public class TestRandVals {
    public static void main(String[] args) {
        System.out.println(RandVals.RANDOM_INT);
        System.out.println(RandVals.RANDOM_LONG);
        System.out.println(RandVals.RANDOM_FLOAT);
        System.out.println(RandVals.RANDOM_DOUBLE);
    }
}
/* output

8
-32032247016559954
-8.5939291E18
5.779976127815049
*/

9.8嵌套接口

package chapter9interfaces.nesting;

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

         @Override
         public void f() {

         }
     }

     private class BImp2 implements B{

         @Override
         public void f() {

         }
     }

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

         @Override
         public void f() {

         }
     }
     private class CImp2 implements C{

         @Override
         public void f() {

         }
     }
     private interface D{
         void f();
     }
     private class DImp implements D{

         @Override
         public void f() {

         }
     }
     public class DImp2 implements D{

         @Override
         public void f() {

         }
     }
     public D getD(){return new DImp2();}
     private D dRef;
     public void receiveD(D d){
         dRef = d;
         dRef.f();
     }
}

interface E{
    interface G{
        void f();
    }
    public interface H{ //redundant public
        void f();
    }
    void g();
//    private interface  I{}  在接口里面 不能private
}

public class NestingInterfaces {
    public class BImp implements A.B{

        @Override
        public void f() {

        }
    }
    class CImp implements A.C{

        @Override
        public void f() {

        }
    }
//    class DImp implements A.D{ // A.D 私有
//        @Override
//        public void f() {
//
//        }
//    }

    class Eimp implements E{ //不需要实现嵌套在其内部的任何接口

        @Override
        public void g() {

        }
    }

    class EGImp implements E.G{

        @Override
        public void f() {

        }
    }
    class EImp2 implements E{

        @Override
        public void g() {

        }
        class EG implements E.G{

            @Override
            public void f() {

            }
        }
    }

    public static void main(String[] args) {
        A a = new A();
//        A.D ad = a.getD(); // A.D 私有
//        A.DImp2 di2 = a.getD(); //a.getD() 返回的是A.D 
        A.DImp2 di2 = (A.DImp2)a.getD(); //a.getD() 返回的是A.D 
//        a.getD().f(); // 接口的f()
        A a2 = new A();
        a2.receiveD(a.getD());
    }
}

9.9接口与工厂

工厂模式的结构
package chapter9interfaces;

interface Service{
    void method1();
    void method2();
}

interface ServiceFactory{ // 生成某个接口的对象
    Service getService();
}

class Implementation1 implements Service{
    Implementation1(){} // package access

    @Override
    public void method1() {
        System.out.println("Implementation1.method1()");
    }

    @Override
    public void method2() {
        System.out.println("Implementation1.method2()");
    }
}

class Implementation1Factory implements ServiceFactory{

    @Override
    public Service getService() {
        return new Implementation1();  //生成接口的某个实现的对象
    }
}

class Implementation2 implements Service{
    Implementation2(){} // package access

    @Override
    public void method1() {
        System.out.println("Implementation2.method1()");
    }

    @Override
    public void method2() {
        System.out.println("Implementation1.method1()");
    }
}

class Implementation2Factory implements ServiceFactory{

    @Override
    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());
        serviceConsumer(new Implementation2Factory());

    }
}
/*
Implementation1.method1()
Implementation1.method2()
Implementation2.method1()
Implementation1.method1()
 */

package chapter9interfaces;

interface Game{boolean move();}
interface GameFactory{Game getGame();}

class Checkers implements Game{ //西洋跳棋
    private int moves = 0;
    private static final int MOVES =3;

    @Override
    public boolean move() {
        System.out.println("Checkers move " + moves);
        return ++moves != MOVES;
    }
}

class CheckersFactory implements GameFactory{

    @Override
    public Game getGame() {
        return new Checkers();
    }
}

class Chess implements Game{
    private int moves = 0;
    private static final int MOVES =4;

    @Override
    public boolean move() {
        System.out.println("Chess " + moves);
        return ++moves != MOVES;
    }
}

class ChessFactory implements GameFactory{

    @Override
    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());
    }
}

package chapter9interfaces;

import chapter8polymorphism.Shape.Circle;

interface Cycle{
    int wheels();
    void balance();
}

interface CycleFactory{
    Cycle getCycle();
}

class Unicycles implements Cycle{

    @Override
    public int wheels() {
        return 1;
    }

    @Override
    public void balance() {
        System.out.println("Unicycle.balance");
    }
}

class UnicycleFactory implements CycleFactory{

    @Override
    public Cycle getCycle() {
        return new Unicycles();
    }
}

class Bicycles implements Cycle{

    @Override
    public int wheels() {
        return 2;
    }

    @Override
    public void balance() {
        System.out.println("Bicycle.balance");
    }
}

class BicyclesFactory implements CycleFactory{

    @Override
    public Cycle getCycle() {
        return new Bicycles();
    }
}
class Tricycles implements Cycle{

    @Override
    public int wheels() {
        return 2;
    }

    @Override
    public void balance() {
        System.out.println("Tricycle.balance");
    }
}

class TricyclesFactory implements CycleFactory{

    @Override
    public Cycle getCycle() {
        return new Tricycles();
    }
}


public class E18Cycle {
    public static void go(CycleFactory cf){
        Cycle cycle = cf.getCycle();
        System.out.println("wheels is : " + cycle.wheels());
        cycle.balance();
    }

    public static void main(String[] args) {
        go(new UnicycleFactory());
        go(new TricyclesFactory());
        go(new TricyclesFactory());
    }
}

package chapter9interfaces;

interface Tossing {
    boolean event();
}

interface TossingFactory {
    Tossing getTossing();
}

class CoinTossing implements Tossing {
    private int events;
    private static final int EVENTS = 2;

    @Override
    public boolean event() {
        System.out.println("Coin tossing event " + events);
        return ++events != EVENTS;
    }
}

class  CoinTossingFactory implements TossingFactory{

    @Override
    public Tossing getTossing() {
        return new CoinTossing();
    }
}


class DiceTossing implements Tossing {
    private int events;
    private static final int EVENTS = 6;

    @Override
    public boolean event() {
        System.out.println("Dice tossing event " + events);
        return ++events != EVENTS;
    }
}

class  DiceTossingFactory implements TossingFactory{

    @Override
    public Tossing getTossing() {
        return new DiceTossing();
    }
}
public class E19Tossing { // 抛,掷;
    public static void tossing(TossingFactory tf){
        Tossing tossing = tf.getTossing();
        while (tossing.event())
            ;

    }
    public static void main(String[] args) {
        tossing(new CoinTossingFactory());
        tossing(new DiceTossingFactory());


    }
}

9.10总结

恰当的选择是 优先选择类而不是接口。

 posted on 2019-11-05 15:06  erinchen  阅读(206)  评论(0编辑  收藏  举报