– Cześć, Amigo! Dziś zgłębimy kolejny ciekawy temat. A dokładnie, zapisywanie i ładowanie (rekonstrukcja) obiektów. Załóżmy, że mamy klasę Cat:
class Cat
{
public String name;
public int age;
public int weight;
}
I powiedzmy, że chcemy dodać wygodny mechanizm do zapisywania do pliku oraz ładowania z pliku.
Moglibyśmy zrobić to w ten sposób:
class Cat {
public String name;
public int age;
public int weight;
public void save(PrintWriter writer) throws Exception {
writer.println(name);
writer.println(age);
writer.println(weight);
writer.flush();
}
public void load(BufferedReader reader) throws Exception {
name = reader.readLine();
age = Integer.parseInt(reader.readLine());
weight = Integer.parseInt(reader.readLine());
}
}
– Wow! – To takie łatwe. Po prostu zapisujemy wartości każdego argumentu, po jednym w każdej linii. Kiedy ładujemy plik, odczytujemy je w tej samej kolejności. To idealne rozwiązanie.
– Dzięki, Amigo. Teraz możesz napisać metody save i load dla tej grupy klas:
class Cat
{
public String name;
public int age;
public int weight;
}
class Dog
{
public String name;
public int age;
}
class Human
{
public Cat cat;
public Dog dog;
}
Masz obiekt Human, który może mieć jednego psa i jednego kota.
– Mam rozwiązanie:
class Cat {
public String name;
public int age;
public int weight;
public void save(PrintWriter writer) throws Exception {
writer.println(name);
writer.println(age);
writer.println(weight);
writer.flush();
}
public void load(BufferedReader reader) throws Exception {
name = reader.readLine();
age = Integer.parseInt(reader.readLine());
weight = Integer.parseInt(reader.readLine());
}
}
class Dog {
public String name;
public int age;
public void save(PrintWriter writer) throws Exception {
writer.println(name);
writer.println(age);
writer.flush();
}
public void load(BufferedReader reader) throws Exception {
name = reader.readLine();
age = Integer.parseInt(reader.readLine());
}
}
public class Human {
public Cat cat;
public Dog dog;
public void save(PrintWriter writer) throws Exception {
cat.save(writer);
dog.save(writer);
}
public void load(BufferedReader reader) throws Exception {
cat.load(reader);
dog.load(reader);
}
}
– To bardzo dobre rozwiązanie. Ale co się dzieje, gdy Human ma psa, ale nie ma kota?
Gdzie są sprawdzane typy null?
– Już to naprawiam:
public class Human {
public Cat cat;
public Dog dog;
public void save(PrintWriter writer) throws Exception {
if (cat != null)
cat.save(writer);
if (dog != null)
dog.save(writer);
}
public void load(BufferedReader reader) throws Exception {
cat = new Cat();
cat.load(reader);
dog = new Dog();
dog.load(reader);
}
}
– Nadal nie jest całkiem poprawnie. Masz dwa błędy:
1) Osoba może nie mieć kota lub psa, ale i tak zostaną one utworzone, gdy metoda load zostanie wywołana
2) Jeśli zapisujemy tylko psa, jego dane zostaną odczytane przez kota po jego załadowaniu.
– A więc co powinienem zrobić?
– Nie możemy pominąć zapisu zmiennych, w przeciwnym razie będziemy mieli problemy z ich odczytem. Musisz się upewnić, że zmienne, które mają wartość null podczas operacji zapisu są ustawione na null podczas operacji ładowania. Oto moja wersja:
public class Human {
public Cat cat;
public Dog dog;
public void save(PrintWriter writer) throws Exception {
String isCatPresent = cat != null ? "tak" : "nie";
writer.println(isCatPresent);
writer.flush();
if (cat != null)
cat.save(writer);
String isDogPresent = dog != null ? "tak" : "nie";
writer.println(isDogPresent);
writer.flush();
if (dog != null)
dog.save(writer);
}
public void load(BufferedReader reader) throws Exception {
String isCatPresent = reader.readLine();
if (isCatPresent.equals("tak")) {
cat = new Cat();
cat.load(reader);
}
String isDogPresent = reader.readLine();
if (isDogPresent.equals("tak")) {
dog = new Dog();
dog.load(reader);
}
}
}
– Tak, podoba mi się to rozwiązanie.
– Zgadza się, jest fajne.
GO TO FULL VERSION