1.抽象类
java提供一个叫做抽象类。若类中包含抽象方法,该类必须限定为抽象的。
编译器不会为抽象类创建对象。
如果继承了一个抽象类,那么导出类必须实现继承的抽象方法。如果不这样,那么导出类也是抽象类,必须有abstract关键字。
练习一:
import java.util.Random;
abstract class Rodent{
abstract void voice();
abstract void eat();
}
class Mouse extends Rodent {
@Override
void voice() {
System.out.println("Zhi");
}
@Override
void eat(){
System.out.println("everything");
}
}
class Gerbil extends Rodent{
@Override
void voice() {
System.out.println("perhaps Zhi");
}
@Override
void eat() {
System.out.println("perhaps everything");
}
}
class Hamster extends Rodent{
@Override
void voice() {
System.out.println("I don't know");
}
@Override
void eat() {
System.out.println("I don't know, maybe everything");
}
}
class RandomRodentGenerator{
private Random rand =new Random(42);
Rodent next() {
switch(rand.nextInt(3)) {
default:
case 0: return new Mouse();
case 1: return new Gerbil();
case 2: return new Hamster();
}
}
}
public class Test1 {
private static RandomRodentGenerator gen=new RandomRodentGenerator();
public static void main(String[] args) {
Rodent[] array=new Rodent[9];
for(int i=0;i
练习4:
abstract class Hello{}
class NiHao extends Hello{
void print() {
System.out.println("hihao");
}
}
public class Test4 {
static void output(Hello temp) {
((NiHao)temp).print();//如果基类里加abstract,就不用向下转型了
}
public static void main(String[] args) {
Hello temp=new NiHao();
output(temp);
}
}
注意,可以在interface前加public关键字(但仅限该接口与其同名的文件被定义)。接口内可以有域,但域被隐式为public,static和final的。接口中方法的定义就算不加public,他们隐式的是public。如果实现接口,则实现的方法必须加public。
2.完全解耦
如果一个方法操作的是类而非接口,那么我们只能使用这个类及其子类。创建一个鞥根据所传递的参数对象不同而不同行为的方法,被称为策略设计模式。策略是传递进去的参数对象,包括要执行的代码。
这里提到了split函数,作用是将String类型以传进来的参数作为边界,将String对象分隔开,然后返回一个String[]。
在书中的例子中,filter无法适配processor,因为filter不是接口的实现,而且此时我们无法改动filter。这时候我们采用适配器设计模式。
练习11:
interface Processor{
String name();
Object process(Object input);
}
class Apply{
public static void process(Processor p,Object s) {
System.out.println("Using Processor"+p.name());
System.out.println(p.process(s));
}
}
class ChangeString{
//不知道每一对字符是什么含义,估计是所有可以成对的都要换
String name() {
return getClass().getSimpleName();
}
String process(String s) {
char[] array=s.toCharArray();
for(int i=0;i
3.java多重继承
接口没有具体实现。所以没有任何与接口有关的储存。java中可以继承多个接口。使用接口的核心原因是能向上转型为多个基类型。使用接口第二个原因是防止客户端程序员创建该类的对象。
通过继承扩展接口extends用于单一类,但可以引用多个基类接口。
练习14,15:
interface Study{
void write();
void read();
}
interface Eat{
void chew();
void drink();
}
interface Play{
void run();
void jump();
}
interface People extends Study,Eat,Play{
void sleep();
}
abstract class Student{
abstract void doHomework();
}
class GoodStudent extends Student implements People{
void doHomework() {
System.out.println("writing homework.");
}
public void write() {
System.out.println("writing");
}
public void read() {
System.out.println("reading");
}
public void chew() {
System.out.println("chewing");
}
public void drink() {
System.out.println("drink");
}
public void run() {
System.out.println("running");
}
public void jump() {
System.out.println("jumping");
}
public void sleep() {
System.out.println("sleeping");
}
}
public class Test14And15 {
static void studyInclassroom(Study people) {
System.out.println("studying in the classroom.");
}
static void eatInRestaurant(Eat people) {
System.out.println("eating in the restaurant.");
}
static void playonPlayground(Play people) {
System.out.println("playing on the playground.");
}
static void lazyPeople(People people) {
System.out.println("Don't bother me,I'm sleeping.");
}
public static void main(String[] args) {
GoodStudent stu=new GoodStudent();
stu.doHomework();
studyInclassroom(stu);
eatInRestaurant(stu);
playonPlayground(stu);
lazyPeople(stu);
}
}
注意,在打算组合的不同接口中使用相同方法名通常会造成代码可读性的混乱,尽量避免这种情况。
4.适配接口
接口一种常见用法就是策略设计模式。这里书上简要介绍了Scanner类,它接受的是一个Readable(它是单独为Scanner)的接口,通过这个可使它作用更多类。所以如果创建一个新类想让Scanner可以作用,那么就让他实现Readable。
Readable接口只要求实现read()方法。
练习十六:
import java.io.IOException;
import java.nio.CharBuffer;
import java.util.Random;
import java.util.Scanner;
class CharArray{
private static Random rand =new Random(42);
private static final char[] arr="abcdefghijklmnopqrstuvwxyz".toCharArray();
public char next() {return arr[rand.nextInt(26)];}
}
class AdaptedCharArray extends CharArray implements Readable{
private int count;
public AdaptedCharArray(int count) {
this.count=count;
}
@Override
public int read(CharBuffer cb) throws IOException {
if(count--==0) {
return -1;
}
for(int i=0;i<10;i++) {
cb.append(next());
}
cb.append(" ");
return 10;
}
}
public class Test16 {
public static void main(String[] args) {
Scanner sc=new Scanner(new AdaptedCharArray(10));
while(sc.hasNext()) {
System.out.println(sc.next());
}
}
}
接口中的域是public,static且final的。
5.接口嵌套
接口可以嵌套在类或其他接口中。
6.接口与工厂
生成遵循某个接口的对象的典型方式是工厂方法设计模式。通过这种方法使得代码与接口完全分离,这样就使得我们透明地将某个实现替换为另一个实现。
练习十八:
interface Cycle{
void bike();
}
interface CycleFactory{
Cycle getCycle();
}
//interface
class Unicycle implements Cycle{
public void bike() {
System.out.println("biking unicycle");
}
}
class UnicycleFactory implements CycleFactory{
public Cycle getCycle() {
return new Unicycle();
}
}
//unicycle
class Bicycle implements Cycle{
public void bike() {
System.out.println("biking bicycle");
}
}
class BicycleFactory implements CycleFactory{
public Cycle getCycle() {
return new Bicycle();
}
}
//bicycle
class Tricycle implements Cycle{
public void bike() {
System.out.println("biking tricycle");
}
}
class TricycleFactory implements CycleFactory{
public Cycle getCycle() {
return new Tricycle();
}
}
//tricycle
public class Test18 {
static void cycleConsumer(CycleFactory fact) {
Cycle cycle=fact.getCycle();
cycle.bike();
}
public static void main(String[] args) {
cycleConsumer(new UnicycleFactory());
cycleConsumer(new BicycleFactory());
cycleConsumer(new TricycleFactory());
}
}
练习十九:
import java.util.Random;
//interface
interface RandomTrial{
void randomEvents();
}
interface DoTrial{
RandomTrial getTrial();
}
//interface
class Coin implements RandomTrial{
private static Random rand=new Random(42);
public void randomEvents() {
if(rand.nextBoolean()) {
System.out.println("head");
}else {
System.out.println("tail");
}
}
}
class DoCoin implements DoTrial{
public RandomTrial getTrial() {
return new Coin();
}
}
//coin
class Dice implements RandomTrial{
private static Random rand=new Random(42);
public void randomEvents() {
int num=rand.nextInt(6)+1;
switch(num) {
case 0:{System.out.println("point: "+num);break;}
case 1:{System.out.println("point: "+num);break;}
case 2:{System.out.println("point: "+num);break;}
case 3:{System.out.println("point: "+num);break;}
case 4:{System.out.println("point: "+num);break;}
case 5:{System.out.println("point: "+num);break;}
}
}
}
class DoDice implements DoTrial{
public RandomTrial getTrial() {
return new Dice();
}
}
public class Test19 {
static void Trial(DoTrial fact) {
RandomTrial r=fact.getTrial();
r.randomEvents();
}
public static void main(String[] args) {
for(int i=0;i<10;i++) {
//Trial(new DoCoin());
Trial(new DoDice());
}
}
}



