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总结
恰当的选择是 优先选择类而不是接口。