Java 學習記錄48 — Interface challenge

張小雄
5 min readMar 29, 2021

--

Create a simple interface (tip: name it Saveable or ISaveable)

That interface allows an object to be saved to some sort of storage medium. (tip: use arraylist)

The exact type of medium is not known to the interface (nor to the classes that implement it).

The interface will just specify two methods, one to return an ArrayList of values to be saved

and the other to populate the object’s fields from an ArrayList (parameter).

Create a few sample classes that implement your Saveable interface (we’ve used the idea of a game,

with Players and Monsters, but you can create any type of classes that you want).

Override the toString() method for each of your classes so that they can be easily printed to enable

the program to be tested easier.

In Main, write a method that takes an object that implements the interface as a parameter and

“saves” the values e.g. calls the method defined in the interface.

We haven’t covered I/O yet, so your method should just print the values to the screen.

Also in the Main class, write a method that restores the values to a Saveable object

e.g. calls the method from the interface for populating fields (see above).

Again, we are not going to use Java file I/O; instead use the readValues() method below to

simulate getting values from a file — this allows you to type as many values as your class

requires, and returns an ArrayList.

There is a whole Java I/O section later in the course where you will get to use files, etc.

public static ArrayList<String> readValues () {
ArrayList<String> values = new ArrayList<String>();
Scanner scanner = new Scanner(System.in);
boolean quit = false;
int index = 0;
System.out.println("Choose\n" +
"1 to enter a string\n" +
"0 to quit");
while (!quit) {
System.out.print("Choose an option: ");
int choice = scanner.nextInt();
scanner.nextLine();
switch (choice) {
case 0:
quit = true;
break;
case 1:
System.out.print("Enter a string: ");
String stringInput = scanner.nextLine();
values.add(index, stringInput);
index++;
break;
}
}
return values;
}

參考答案:

ISaveable.java

import java.util.ArrayList;
import java.util.List;
public interface ISaveable {
List<String> write();
void read(List<String> savedValues);
}

Player.java

import java.util.ArrayList;
import java.util.List;
public class Player implements ISaveable {
private String name;
private int hitPoints;
private int strength;
private String weapon;
public Player(String name, int hitPoints, int strength) {
this.name = name;
this.hitPoints = hitPoints;
this.strength = strength;
this.weapon = "Sword";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getHitPoints() {
return hitPoints;
}
public void setHitPoints(int hitPoints) {
this.hitPoints = hitPoints;
}
public int getStrength() {
return strength;
}
public void setStrength(int strength) {
this.strength = strength;
}
public String getWeapon() {
return weapon;
}
public void setWeapon(String weapon) {
this.weapon = weapon;
}
@Override
public String toString() {
return "Player{" +
"name='" + name + '\'' +
", hitPoints=" + hitPoints +
", strength=" + strength +
", weapon='" + weapon + '\'' +
'}';
}
@Override
public List<String> write() {
List<String> values = new ArrayList<String>();
values.add(0, this.name);
values.add(1, "" + this.hitPoints);
values.add(2, "" + this.strength);
values.add(3, this.weapon);
return values;
}
@Override
public void read(List<String> savedValues) {
if(savedValues != null && savedValues.size() >0) {
this.name = savedValues.get(0);
this.hitPoints = Integer.parseInt(savedValues.get(1));
this.strength = Integer.parseInt(savedValues.get(2));
this.weapon = savedValues.get(3);
}
}
}

Monster.java

import java.util.ArrayList;
import java.util.List;
public class Monster implements ISaveable {
private String name;
private int hitPoints;
private int strength;
public Monster(String name, int hitPoints, int strength) {
this.name = name;
this.hitPoints = hitPoints;
this.strength = strength;
}
public String getName() {
return name;
}
public int getHitPoints() {
return hitPoints;
}
public int getStrength() {
return strength;
}
@Override
public List<String> write() {
ArrayList<String> values = new ArrayList<String>();
values.add(0, this.name);
values.add(1, "" + this.hitPoints);
values.add(2, "" + this.strength);
return values;
}
@Override
public void read(List<String> savedValues) {
if (savedValues != null && savedValues.size() > 0) {
this.name = savedValues.get(0);
this.hitPoints = Integer.parseInt(savedValues.get(1));
this.strength = Integer.parseInt(savedValues.get(2));
}
} @Override
public String toString() {
return "Monster{" +
"name='" + name + '\'' +
", hitPoints=" + hitPoints +
", strength=" + strength +
'}';
}
}

MainRead.java

import java.util.ArrayList;
import java.util.Scanner;
public class MainRead { public static void main(String[] args) {

Player tim = new Player("Tim", 10, 15);
System.out.println(tim.toString());
saveObject(tim);
tim.setHitPoints(8);
System.out.println(tim);
tim.setWeapon("Stormbringer");
saveObject(tim);
// loadObject(tim);
System.out.println(tim);
ISaveable werewolf = new Monster("Werewolf", 20, 40);
System.out.println("Strength = " + ((Monster) werewolf).getStrength());
saveObject(werewolf);
} public static ArrayList<String> readValues() {
ArrayList<String> values = new ArrayList<String>();
Scanner scanner = new Scanner(System.in);
boolean quit = false;
int index = 0;
System.out.println("Choose\n" +
"1 to enter a string\n" +
"0 to quit");
while (!quit) {
System.out.print("Choose an option: ");
int choice = scanner.nextInt();
scanner.nextLine();
switch (choice) {
case 0:
quit = true;
break;
case 1:
System.out.print("Enter a string: ");
String stringInput = scanner.nextLine();
values.add(index, stringInput);
index++;
break;
}
}
return values;
}
public static void saveObject(ISaveable objectToSave) {
for (int i = 0; i < objectToSave.write().size(); i++) {
System.out.println("Saving " + objectToSave.write().get(i) + " to storage device");
}
}
public static void loadObject(ISaveable objectToLoad) {
ArrayList<String> values = readValues();
objectToLoad.read(values);
}
}

這篇挑戰我是沒做出來,看不懂需求,直接看 Tim 的講解

後來看到討論區快笑死,前面幾則讚數高的都在罵這個挑戰太模糊

我自己在理解後嘗試簡化代碼,改過的代碼理解起來比較簡單

ISaveable.java

import java.util.List;public interface ISaveable {
List<String> write();
void update(List<String> savedValues);
}

PlayerOwnVersion.java

import java.util.ArrayList;
import java.util.List;
public class PlayerOwnVersion implements ISaveable { private String name;
private String weapon;
private int hitPoints;
private int strength;
public PlayerOwnVersion(String name, int hitPoints, int strength) {
this.name = name;
this.hitPoints = hitPoints;
this.strength = strength;
weapon = "Sword";
}
@Override
public List<String> write() {
List<String> values = new ArrayList<>();
values.add(0, name);
values.add(1, "" + hitPoints);
values.add(2, "" + strength);
values.add(3, weapon);
return values;
}
@Override
public void update(List<String> savedValues) {
if (savedValues != null && savedValues.size() > 0) {
name = savedValues.get(0);
hitPoints = Integer.parseInt(savedValues.get(1));
strength = Integer.parseInt(savedValues.get(2));
weapon = savedValues.get(3);
}
}
@Override
public String toString() {
return "Players{" +
"name='" + name + '\'' +
", hitPoints=" + hitPoints +
", strength=" + strength +
", weapon='" + weapon + '\'' +
'}';
}
}

MainReadOwnVersion.java

import java.util.ArrayList;
import java.util.Scanner;
public class MainReadOwnVersion { public static void main(String[] args) {
ISaveable player = new PlayerOwnVersion("Tim",20,40);
saveObject(player);
editObject(player);
loadObject(player);
}
public static void saveObject(ISaveable objectToSave) {
for (int i = 0; i < objectToSave.write().size(); i++) {
String state = "";
switch (i) {
case 0:
state = " name ";
break;
case 1:
state = " hit point ";
break;
case 2:
state = " strength ";
break;
case 3:
state = " weapon ";
break;
}
System.out.println("Saving " + objectToSave.write().get(i) + state + "to storage device.");
}
}
public static void loadObject(ISaveable objectToLoad) {
System.out.println(objectToLoad);
}
public static void editObject(ISaveable objectToLoad){
Scanner scanner = new Scanner(System.in);
ArrayList<String> values = new ArrayList<String>();
System.out.print("Enter a character name: ");
String characterName = scanner.nextLine();
System.out.print("Enter a hitPoints: ");
String hitPoints = scanner.nextLine();
System.out.print("Enter a strength: ");
String strength = scanner.nextLine();
System.out.print("Enter a weapon: ");
String weapon = scanner.nextLine();
values.add(0, characterName);
values.add(1, hitPoints);
values.add(2, strength);
values.add(3, weapon);
objectToLoad.update(values); }}

值得注意的是

參數放的若是 Interface 在案例中為 List

那任何 implement 該 Interface 的 Class

都能被使用

在案例中就是 參數用 List

那麼放入 ArrayList 跟 LinkedList 都可以

public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
----
public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable

想出這個設計方式的人真是厲害

拓展性翻了好幾倍

假設沒有此設計方式

五種不同的 List 就要寫五個 Method 出來

而且一個 Class 可以 implements 多個 Interface

但繼承父類 則只能選一個

但如果要實現特定Class裡面的Method時

就要在前面用(該Class)來進行 Casting

如:(特定Class).Method

不能寫做 List.Method

因為在 List 裡面就沒有那個 Method

案例中為

ISaveable werewolf = new Monster("Werewolf", 20, 40);
System.out.println("Strength = " + ((Monster) werewolf).getStrength());

若是直接用 werewolf.getStrength() 是會報錯的

--

--

張小雄
張小雄

Written by 張小雄

記錄成為軟體工程師的過程

No responses yet