文章目录
一、类的关系
技巧:自动创建构造器——
1. 继承
- 事例:媒体资料库
Database
import java.util.ArrayList;
public class Database {
//代码复制严重
private ArrayList<CD> listCD = new ArrayList<CD>();
private ArrayList<DVD> listDVD = new ArrayList<DVD>();
//添加CD信息
public void add(CD cd) {
listCD.add(cd);
}
public void add(DVD dvd) {//函数重载
listDVD.add(dvd);
}
//输出所有CD的信息
public void list() {
for(CD cd : listCD) {
cd.print();
}
for(DVD dvd : listDVD) {
dvd.print();
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Database db = new Database();
//子类对象可以当作父类的对象使用
db.add(new CD("从前有1首歌", "哲斯沃斯基.卞德", 4, 60, "好好听!"));
db.add(new CD("从前有2首歌", "哲斯沃斯基.卞德", 4, 60, "好好听!"));
db.add(new CD("从前有3首歌", "哲斯沃斯基.卞德", 4, 60, "好好听!"));
db.add(new CD("从前有4首歌", "哲斯沃斯基.卞德", 4, 60, "好好听!"));
db.add(new DVD("我的**之旅", "霞基巴.卞德", 60, "好好看!"));
db.list();
}
}
CD
import java.util.ArrayList;
public class Database {
//代码复制严重
private ArrayList<CD> listCD = new ArrayList<CD>();
private ArrayList<DVD> listDVD = new ArrayList<DVD>();
//添加CD信息
public void add(CD cd) {
listCD.add(cd);
}
public void add(DVD dvd) {//函数重载
listDVD.add(dvd);
}
//输出所有CD的信息
public void list() {
for(CD cd : listCD) {
cd.print();
}
for(DVD dvd : listDVD) {
dvd.print();
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Database db = new Database();
db.add(new CD("从前有1首歌", "哲斯沃斯基.卞德", 4, 60, "好好听!"));
db.add(new CD("从前有2首歌", "哲斯沃斯基.卞德", 4, 60, "好好听!"));
db.add(new CD("从前有3首歌", "哲斯沃斯基.卞德", 4, 60, "好好听!"));
db.add(new CD("从前有4首歌", "哲斯沃斯基.卞德", 4, 60, "好好听!"));
db.add(new DVD("我的**之旅", "霞基巴.卞德", 60, "好好看!"));
db.list();
}
}
DVD
public class DVD {//同CD
private String title;
private String director;
private int playingTime;
private boolean gotIt = false;
private String comment;
public DVD(String title, String director, int playingTime, String comment) {
super();
this.title = title;
this.director = director;
this.playingTime = playingTime;
this.comment = comment;
}
//输出DVD信息
public void print() {
// TODO Auto-generated method stub
System.out.println("DVD: " + title + "————" + director);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
}
}
- CD和DVD类的代码相似性高,Database中创建CD和DVD的代码大量重复,代码复制严重
改进:
Database
import java.util.ArrayList;
public class Database {
//修改:
private ArrayList<Item> listItem = new ArrayList<Item>();
//添加CD信息
public void add(Item item) {
listItem.add(item);
}
//输出所有CD的信息
public void list() {
for(Item item : listItem) {
item.print();
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Database db = new Database();
db.add(new CD("从前有1首歌", "哲斯沃斯基.卞德", 4, 60, "好好听!"));
db.add(new CD("从前有2首歌", "哲斯沃斯基.卞德", 4, 60, "好好听!"));
db.add(new CD("从前有3首歌", "哲斯沃斯基.卞德", 4, 60, "好好听!"));
db.add(new CD("从前有4首歌", "哲斯沃斯基.卞德", 4, 60, "好好听!"));
db.add(new DVD("我的**之旅", "霞基巴.卞德", 60, "好好看!"));
db.list();
}
}
父类Item
public class Item {
// 不能用private,否则子类不能继承成员变量
//方法一: protected: 自己、同一个包和子类能够访问
protected String title;
private int playingTime;//与子类CD中重复
protected boolean gotIt = false;
private String comment;
public Item(int playingTime, String comment) {
super();
this.playingTime = playingTime;
this.comment = comment;
}
//父类和子类中有相同的成员变量,在父类中操作时修改的是父类的该变量
public void setPlayingTime(int playingTime) {
this.playingTime = playingTime;
}
public void print() {
System.out.println(comment);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
}
}
子类CD
public class CD extends Item{//CD extends CD扩展了Item,使CD成为Item的子类
//如果父类和子类中有相同的成员变量,则父类的变量将会被隐藏
// private String title; //代码复制,将相同的成员变量放入父类Item
private String artist;
private int numofTracks;
private int playingTime;//与父类Item中重复
// private boolean gotIt = false;
// private String comment;
//构造器
public CD(String title, String artist, int numofTracks, int playingTime, String comment) {
super(playingTime, comment);//根据super()的参数在父类中寻找对应的构造器,
//父类的private变量仍然不能在子类中调用
this.title = title;
this.artist = artist;
this.numofTracks = numofTracks;
setPlayingTime(30);//这里修改的是父类中的playingTime
this.playingTime = playingTime;
// this.comment = comment;
}
// //输出CD信息
public void print() { //如果CD没有print函数,则CD将继承Item的print函数
// TODO Auto-generated method stub
System.out.println("CD: " + title + "————" + artist);
super.print(); //用super可以调用父类的print()
}
public static void main(String[] args) {
// TODO Auto-generated method stub
CD cd = new CD("从前有4首歌", "哲斯沃斯基.卞德", 4, 60, "好好听!");
cd.print();
}
}
子类DVD
public class DVD extends Item {//DVD是Item的子类
// private String title;
private String director;
// private int playingTime;
// private boolean gotIt = false;
// private String comment;
public DVD(String title, String director, int playingTime, String comment) {
super(playingTime, comment);
this.title = title;
this.director = director;
// this.playingTime = playingTime;
// this.comment = comment;
}
//输出DVD信息
public void print() {
// TODO Auto-generated method stub
System.out.println("DVD: " + title + "————" + director);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
}
}
- 父类与子类的关系的确定:public class 子类 extends 父类 { }
- 子类和父类的联系:子类可以继承父类的变量和函数,但如果父类的变量设置访问属性为private,则子类无法访问
- 子类无法访问父类的private变量:
方法一:
设置父类变量的访问属性为protected:自己、同一个包和子类能够访问
方法二:
在父类中设置构造函数,在子类构造器的super()填入需要的变量,super()会根据super()的参数在父类中寻找对应的构造器完成变量的初始化,但是在子类中就无法操作父类的private变量(可以用super.父类的函数来间接操作在父类中的变量)
(详见代码) - 在父类和子类中有同名的变量,在子类函数中的变量就是子类自己的,在父类函数中的变量就是父类自己的,在哪里就操作哪里的变量
2. 子类
- 子类和子类型
- 子类型与赋值
- 子类的对象都可以交给父类
- 子类和参数传递
- 子类和容器
3. 多态
- 多态变量
- 造型Cast
-
造型的正确用法
-
造型
-
向上造型:
- 函数调用的绑定与覆盖override
-
绑定
所以,在调用函数时,要看运行时实际管理的对象是谁来调用其的函数 -
覆盖
所以,在操作 实际管理的类型是子类的时侯,子类的函数会将父类的同名同参函数覆盖 -
因为上两者,所以在调用item.print()时,会调用子类的print()
-
[item在运行时的实际管理的类型是子类,所以函数绑定的是子类的print(),而子类的print()又会覆盖父类的print()]
4. Object类
- 所有类继承
- 所以所有类均能继承Object类的函数
- Object类的函数
- 自动创建toString()——
- 选中需要展示的变量后eclipse可自动创建
- 自动创建equals()——
- 此方法需要手动修改:
5. 增加新的子类
- 新的技巧——
-
自动创建子类
-
自动创建继承自父类的构造器
- 增加新的媒体类型
-
不需要修改其它代码,直接扩展,能适应新的数据和内容——可扩展性
-
构建子类的子类,构成更深的继承关系,更有效的表达所有媒体类型
二、城堡游戏
技巧:直接跳转到函数的声明处——
游戏操作:
通过go、bye、help这三个简单的命令完成在城堡中的移动
1. 初步代码:
- Castle类:
import java.util.Scanner;
public class Castle {
private Room currentRoom;
public Castle() {
createRooms();
}
private void createRooms() {
Room outside, labby, pub, study, bedroom;
//制造房间
outside = new Room("城堡外");
labby = new Room("大堂");
pub = new Room("小酒吧");
study = new Room("书房");
bedroom = new Room("卧室");
//初始化房间的出口
outside.setExits(null, labby, study, pub);
labby.setExits(null, null, null, outside);
pub.setExits(null, outside, null, null);
study.setExits(outside, bedroom, null, null);
bedroom.setExits(null, null, null, study);
currentRoom = outside; //从城堡外开始
}
private void printWelcome() {
System.out.println();
System.out.println("欢迎来到城堡!");
System.out.println("这是一个灰常有意思的游戏。");
System.out.println("如果需要帮助。请输入'help'。");
System.out.println();
System.out.println("现在你在" + currentRoom);
System.out.println("出口有:");
if(currentRoom.northExit != null)
System.out.println("north ");
if(currentRoom.eastExit != null)
System.out.println("east ");
if(currentRoom.southExit != null)
System.out.println("south ");
if(currentRoom.westExit != null)
System.out.println("west ");
System.out.println();
}
//以下为用户命令
private void printHelp() {
System.out.println("迷路了吗?你可以做的命令有:go bye help");
System.out.println("如:\tgo east");
}
private void goRoom(String direction) {
Room nextRoom = null;
if(direction.equals("north")) {
nextRoom = currentRoom.northExit;
}
if(direction.equals("east")) {
nextRoom = currentRoom.eastExit;
}
if(direction.equals("south")) {
nextRoom = currentRoom.southExit;
}
if(direction.equals("west")) {
nextRoom = currentRoom.westExit;
}
if(nextRoom == null) {
System.out.println("那里没有门!");
}
else {
currentRoom = nextRoom;
System.out.println("你在" + currentRoom);
System.out.println("出口有:");
if(currentRoom.northExit != null)
System.out.println("north");
if(currentRoom.eastExit != null)
System.out.println("east");
if(currentRoom.southExit != null)
System.out.println("south");
if(currentRoom.westExit != null)
System.out.println("west");
System.out.println();
}
}
public void showPrompt() {
System.out.println("现在你在" + currentRoom);
System.out.println("出口有:");
if(currentRoom.northExit != null)
System.out.println("north ");
if(currentRoom.eastExit != null)
System.out.println("east ");
if(currentRoom.southExit != null)
System.out.println("south ");
if(currentRoom.westExit != null)
System.out.println("west ");
System.out.println();
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner in = new Scanner(System.in);
Castle game = new Castle();
game.printWelcome();
while(true) {
String line = in.nextLine();
String[] words = line.split(" ");
//split("a"):以a为分割,对字符串进行分割,将分割后的字符串分别装入数组返回字符串数组
if(words[0].toLowerCase().equals("help")) {
game.printHelp();
}
else if(words[0].toLowerCase().equals("go")) {
game.goRoom(words[1]);
}
else if(words[0].toLowerCase().equals("bye")) {
break;
}
}
System.out.println("感谢您的光临,再见!");
in.close();
}
}
- Room类:
public class Room {
public String description;
public Room northExit;
public Room eastExit;
public Room southExit;
public Room westExit;
public Room(String description) {
this.description = description;
}
public void setExits(Room north, Room east, Room south, Room west) {
if(north != null)
northExit = north;
if(east != null)
eastExit = east;
if(south != null)
southExit = south;
if(west != null)
westExit = west;
}
@Override
public String toString() {
// TODO Auto-generated method stub
return description;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
}
}
2. 改进一:消除代码复制
- 解决方法
- 此段在Castle类中出现多次
System.out.println("你在" + currentRoom); System.out.println("出口有:"); if(currentRoom.northExit != null) System.out.println("north"); if(currentRoom.eastExit != null) System.out.println("east"); if(currentRoom.southExit != null) System.out.println("south"); if(currentRoom.westExit != null) System.out.println("west"); System.out.println();
- 改进:用函数封装
public void showPrompt() { System.out.println("现在你在" + currentRoom); System.out.println("出口有:"); if(currentRoom.northExit != null) System.out.println("north "); if(currentRoom.eastExit != null) System.out.println("east "); if(currentRoom.southExit != null) System.out.println("south "); if(currentRoom.westExit != null) System.out.println("west "); System.out.println(); }
3.改进二: 降低耦合
1.解决方法: 可扩展性
2. 方法1: 用封装来降低耦合
- 耦合度低,类与类之间的关系不紧密,修改一个类对其它类的影响将会降低
-
问题一:
public String description; public Room northExit; public Room eastExit; public Room southExit; public Room westExit;
-
改进1: 将类的成员变量的访问属性修改成private
private String description; private Room northExit; private Room eastExit; private Room southExit; private Room westExit;
-
问题二:
if(currentRoom.northExit != null) System.out.println("north "); if(currentRoom.eastExit != null) System.out.println("east "); if(currentRoom.southExit != null) System.out.println("south "); if(currentRoom.westExit != null) System.out.println("west ");
- 改进2:
- 封装输出房间出口的函数
- 放在Room类中,切断Castle类与Room类成员变量的连接
public String getExitDesc() { StringBuffer sb = new StringBuffer(); //String不可变,需要用Stringbuffer来拼接大量字符串 if(northExit != null) sb.append("north "); // append()会添加新的字符串到原来的字符串上 if(eastExit != null) sb.append("east "); if(southExit != null) sb.append("south "); if(westExit != null) sb.append("west "); return sb.toString(); }
- StringBuffer的作用:
- 包括String在内的Wrapper类型都是是不可变类型,也就是这种类型的对象一旦创建好之后,再对其进行任何操作也不会改变其的属性和内容,只会再创建一个新的对象连接到旧对象的管理者上
- 总之就是,在拼接字符串时,旧的字符串不会因为拼接了新的字符串而消失
- 所以,如果需要用大量的小字符串拼接成一个长的字符串的时候,就会构造大量的中间的字符串,造成内存浪费
- StringBuffer是可变的,当修改或者追加字符串到原来的对象上是,不会新生成一个字符串,而是在原来的对象上进行修改。这样,就不用分配大量的空间给中间的临时对象了。
具体可查看:Java之中StringBuffer的作用
-
问题三:
Room nextRoom = null; if(direction.equals("north")) { nextRoom = currentRoom.northExit; } if(direction.equals("east")) { nextRoom = currentRoom.eastExit; } if(direction.equals("south")) { nextRoom = currentRoom.southExit; } if(direction.equals("west")) { nextRoom = currentRoom.westExit; }
- 改进3:
- 封装得出房间下一个出口的函数
- 放在Room类中,切断Castle类与Room类成员变量的连接
public Room getExit(String direction) { Room nextRoom = null; if(direction.equals("north")) { nextRoom = northExit; } if(direction.equals("east")) { nextRoom = eastExit; } if(direction.equals("south")) { nextRoom = southExit; } if(direction.equals("west")) { nextRoom = westExit; } return nextRoom; }
4.增加可扩展性
- 基础
- 给Room封装接口getExitDesc()和getExit()后,Room方向和房间的关系就不再收其它类的影响
- 方便增加代码可扩展性
- 方法2:用容器来实现灵活性
- 问题一:
- 用成员变量表示Room方向,代码修改难度高
private Room northExit; private Room eastExit; private Room southExit; private Room westExit;
- 改进1:
private HashMap<String, Room> exits = new HashMap<String, Room>();
- 问题二:修改Room类对应的函数
- setExits(Room north, Room east, Room south, Room west):
public void setExit(String dir, Room room) { exits.put(dir, room); }
- public Room getExit(String direction)
public Room getExit(String direction) { return exits.get(direction); }
- public String getExitDesc()
public String getExitDesc() { StringBuffer sb = new StringBuffer(); //String不可变,需要用Stringbuffer来拼接大量字符串 for(String dir : exits.keySet()) { sb.append(dir); sb.append(' '); } return sb.toString(); }
- creatRoom()中初始化房间出口的部分
outside.setExit("east", labby); outside.setExit("south", study); outside.setExit("west", pub); labby.setExit("west", outside); pub.setExit("east", outside); study.setExit("north", outside); study.setExit("east", bedroom); bedroom.setExit("west", study); //新增出口 pub.setExit("up", labby); labby.setExit("down", pub); currentRoom = outside; //从城堡外开始
- 方法3:以框架+数据来提高可扩展性
- 构建Handler父类及其子类HandlerGo、HandlerBye、HandlerHelp等方便扩展命令
- Handler:
public class Handler {
protected Castle game;
public Handler(Castle game) {
super();
this.game = game;
}
public void doCmd(String word) {
}
public boolean isBye() {
return false;
}
}
- HandlerBye:
public class HandlerBye extends Handler {
public HandlerBye(Castle game) {
super(game);
// TODO Auto-generated constructor stub
}
@Override
public void doCmd(String word) {
}
@Override
public boolean isBye() {
// TODO Auto-generated method stub
return true;
}
}
- HandlerHelp:
public class HandlerHelp extends Handler {
public HandlerHelp(Castle game) {
super(game);
// TODO Auto-generated constructor stub
}
@Override
public void doCmd(String word) {
System.out.println("迷路了吗?你可以做的命令有:go bye help");
System.out.println("如:\tgo east");
}
}
- HandlerGo:
public class HandlerGo extends Handler {
public HandlerGo(Castle game) {
super(game);
// TODO Auto-generated constructor stub
}
@Override
public void doCmd(String word) {
// TODO Auto-generated method stub
game.goRoom(word);
}
}
- 问题三:修改对应的控制代码
while(true) {
String line = in.nextLine();
String[] words = line.split(" ");
//split("a"):以a为分割,对字符串进行分割,将分割后的字符串分别装入数组返回字符串数组
if(words[0].toLowerCase().equals("help")) {
game.printHelp();
}
else if(words[0].toLowerCase().equals("go")) {
game.goRoom(words[1]);
}
else if(words[0].toLowerCase().equals("bye")) {
break;
}
}
- 改进3:封装修正
private HashMap<String, Handler> handlers = new HashMap<String, Handler>();//命令
public void play() {
Scanner in = new Scanner(System.in);
while(true) {
String line = in.nextLine();
String[] words = line.split(" ");
//split("a"):以a为分割,对字符串进行分割,将分割后的字符串分别装入数组返回字符串数组
Handler handler = handlers.get(words[0]);
String value = "";
if(words.length > 1)
value = words[1];
if(handler != null) {
handler.doCmd(value);
if(handler.isBye())
break;
}
}
in.close();
}
5. 修改后的代码
- Castle类:
import java.util.HashMap;
import java.util.Scanner;
public class Castle {
private Room currentRoom;
//改进:
private HashMap<String, Handler> handlers = new HashMap<String, Handler>();//命令
public Castle() {
//改进:
//设置命令
handlers.put("go", new HandlerGo(this));
handlers.put("bye", new HandlerBye(this));
handlers.put("help", new HandlerHelp(this));
createRooms();
}
private void createRooms() {
Room outside, labby, pub, study, bedroom;
//制造房间
outside = new Room("城堡外");
labby = new Room("大堂");
pub = new Room("小酒吧");
study = new Room("书房");
bedroom = new Room("卧室");
//改进:
//初始化房间的出口
outside.setExit("east", labby);
outside.setExit("south", study);
outside.setExit("west", pub);
labby.setExit("west", outside);
pub.setExit("east", outside);
study.setExit("north", outside);
study.setExit("east", bedroom);
bedroom.setExit("west", study);
//新增出口
pub.setExit("up", labby);
labby.setExit("down", pub);
currentRoom = outside; //从城堡外开始
}
private void printWelcome() {
System.out.println();
System.out.println("欢迎来到城堡!");
System.out.println("这是一个灰常有意思的游戏。");
System.out.println("如果需要帮助。请输入'help'。");
System.out.println();
//改进:
showPrompt();
}
//以下为用户命令
//goRoom需要在Castle类里面完成,所以先用曲折的方法完成,
//更有效的方法将在后续学习中完成
public void goRoom(String direction) {
//改进:
Room nextRoom = currentRoom.getExit(direction);
if(nextRoom == null) {
System.out.println("那里没有门!");
}
else {
currentRoom = nextRoom;
//改进:
showPrompt();
}
}
public void showPrompt() {
System.out.println("现在你在" + currentRoom);
System.out.println("出口有:");
System.out.println(currentRoom.getExitDesc());
System.out.println();
}
//改进:
public void play() {
Scanner in = new Scanner(System.in);
while(true) {
String line = in.nextLine();
String[] words = line.split(" ");
//split("a"):以a为分割,对字符串进行分割,将分割后的字符串分别装入数组返回字符串数组
Handler handler = handlers.get(words[0]);
String value = "";
if(words.length > 1)
value = words[1];
if(handler != null) {
handler.doCmd(value);
if(handler.isBye())
break;
}
}
in.close();
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Castle game = new Castle();
game.printWelcome();
game.play();
System.out.println("感谢您的光临,再见!");
}
}
- Room类
import java.util.HashMap;
public class Room {
//改进:
private String description;
//改进:
private HashMap<String, Room> exits = new HashMap<String, Room>();//方向与房间
public Room(String description) {
this.description = description;
}
//改进:
public void setExit(String dir, Room room) {
exits.put(dir, room);
}
@Override
public String toString() {
// TODO Auto-generated method stub
return description;
}
//改进:
// 返回Room能通过的方向
public String getExitDesc() {
StringBuffer sb = new StringBuffer();
//String不可变,需要用Stringbuffer来拼接大量字符串
for(String dir : exits.keySet()) {
sb.append(dir);
sb.append(' ');
}
return sb.toString();
}
public Room getExit(String direction) {
return exits.get(direction);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
}
}
- Handler父类
public class Handler {
protected Castle game;
public Handler(Castle game) {
super();
this.game = game;
}
public void doCmd(String word) {
}
public boolean isBye() {
return false;
}
}
- HandlerBye子类
public class HandlerBye extends Handler {
public HandlerBye(Castle game) {
super(game);
// TODO Auto-generated constructor stub
}
@Override
public void doCmd(String word) {
}
@Override
public boolean isBye() {
// TODO Auto-generated method stub
return true;
}
}
- HandlerHelp子类
public class HandlerHelp extends Handler {
public HandlerHelp(Castle game) {
super(game);
// TODO Auto-generated constructor stub
}
@Override
public void doCmd(String word) {
System.out.println("迷路了吗?你可以做的命令有:go bye help");
System.out.println("如:\tgo east");
}
}
- HandlerGo子类
public class HandlerGo extends Handler {
public HandlerGo(Castle game) {
super(game);
// TODO Auto-generated constructor stub
}
@Override
public void doCmd(String word) {
// TODO Auto-generated method stub
game.goRoom(word);
}
}
三、抽象与接口
1. 抽象
- 抽象的作用
- 抽象类是用来捕捉子类的通用特性的,是被用来创建继承层级里子类的模板。现实中有些父类中的方法确实没有必要写,因为各个子类中的这个方法肯定会有不同;而写成抽象类,这样看代码时,就知道这是抽象方法,而知道这个方法是在子类中实现的,所以有提示作用。
理解抽象的用途:抽象的作用
- 抽象类与抽象函数
- 实现抽象函数
- 抽象的两种含义
2. 细胞自动机——数据与表现分离
程序分析详见:细胞自动机
- 数据与表现分离
- View和Field的关系
- 责任驱动的设计
- 网格化
主要学习程序设计理念
3. 狐狸与兔子
程序分析详见:狐狸与兔子
- 接口
- 实现接口
- 面向接口的编程方式
不理解接口,看个Java 接口 | 菜鸟教程
4.抽象类和接口
一般需要实现多重继承时,可以使用接口
- 共同点
- 都不能被实例化,可以被继承或实现
- 都可以包含抽象函数
- 不同点
- 接口中的函数必须为抽象函数,抽象类中可以有普通函数(接口中的普通方法默认为抽象方法)
- 接口的成员变量必须加public static fianl,且必须赋值
- 接口不能有构造器、不能初始化,抽象类可以
- 一个类只能继承一个抽象类,但是可以实现多个接口
- JDK1.8:
- 用default修饰实现非抽象的方法
- 用static修饰实现接口静态方法
- java类的继承、抽象类与接口的区别
- 控制反转
5. 内部类和匿名类
- 内部类
在一个类内部的类:
- 匿名类
四、总结
1. 类的关系
- 子类型
- 多态
- 函数调用的绑定和覆盖override
- Object类
- 增加新的子类
2. 城堡游戏:代码的优化
3. 抽象与接口
- 抽象
- 细胞自动机——数据与表现分离
- 狐狸和兔子——实现接口
- 内部类和匿名类