Problem z współdziałąniem funkcji

0

Dodałem sobie rzeczy do sejfu za pomocą listy i w funkcji add() jestem w stanie je odczytać, ale nie potrafię ich odczytać za pomocą funkcji printContent() no i połączyć tego z toString w klasie Thing.
To pewnie bardzo proste, ale ja nie mam jeszcze takiej biegłości w tym. Pewnie analogiczne byłoby stworzenie funkcji kasującej jakiś element z listy, ale wtedy i jej efekt trzeba by było jakoś połączyć z funkcją zwracającą ostateczną zawartość listy.
Czy mógłbym prosić o jakieś rozjaśnienie mojego przyćmionego umysłu?

import java.util.ArrayList;

class Safe {
    double weight;
    double volume;
    double maxWeight;
    double maxVolume;

    public Safe(double weight, double volume, double maxWeight, double maxVolume){
        this.weight = weight;
        this.volume = volume;
        this.maxWeight = maxWeight;
        this.maxVolume = maxVolume;
    }
    public void add(Thing thing) {
        ArrayList<String> item_name = new ArrayList<String>();
        item_name.add(thing.getName());
        ArrayList<Double> item_weight = new ArrayList<Double>();
        item_weight.add(thing.getWeight());
        ArrayList<Double> item_volume = new ArrayList<Double>();
        item_volume.add(thing.getVolume());

        for (int i = 0; i < item_name.size(); i++) {
            System.out.println(item_name.get(i));
            System.out.println(item_weight.get(i));
            System.out.println(item_volume.get(i));
        }
    }
    public Thing remove(int index) {
}

    public void printContent(){
    }
}

class Thing {
    protected double weight;
    protected double volume;
    protected String name;

    public Thing(String name, double weight, double volume){
        if(name != null)
            this.name = name;
        else
            this.name = "";
        this.weight = Math.max(weight, 0.0);
        this.volume = Math.max(volume, 0.0);
    }

    public double getWeight(){
        return weight;
    }

    public double getVolume(){
        return volume;
    }
    public String getName(){
        return name;
    }
    @Override
    public String toString() {
        return name + " (" + weight + " kg, " + volume + " l)";
    }
}

class Box extends Thing {
    protected double height;
    protected double width;
    protected double depth;

    public Box(String name, double weight,
               double height, double width, double depth){
        super(name, weight, height*width*depth*1000);
        this.height = height;
        this.width = width;
        this.depth = depth;
    }
    public double getHeight(){
        return height;
    }
    public double getWidht(){
        return width;
    }
    public double getDepth(){
        return depth;
    }
}
public class safe1{
    public static void main(String args[]){
        Safe subject = new Safe(0.100, 0.5, 40, 50);
        subject.add(new Thing("Ball", 1, 3));
        subject.add(new Thing("Torch", 0.5, 1));
        subject.add(new Box("Box1", 5, 0.1,0.5,0.5));
        subject.printContent();
//        subject.remove(2);     //to bylby drugi element z listy
    }
}

0

Masz listy w metodzie a nie w klasie.
W skrocie. Wchodzis w metoda -> tworzysz liste -> dodajesz obiekt -> wychodzisz z metody -> twoja lista to zmienan lokalna wiec jest usuwana
Stworz liste w klasie i do niej dodawaj :)

0
Ziemiak napisał(a):

Masz listy w metodzie a nie w klasie.
W skrocie. Wchodzis w metoda -> tworzysz liste -> dodajesz obiekt -> wychodzisz z metody -> twoja lista to zmienan lokalna wiec jest usuwana
Stworz liste w klasie i do niej dodawaj :)

Bardzo dziękuję za uwagę.
Zrobiłem więc coś takiego w klasie Backpack:

ArrayList<Thing> item = new ArrayList<Thing>();

    public void add(Thing thing) {
        item.add(thing);
    }

    public void printContent(){
        System.out.println(new Thing(Backpack.class.getSimpleName(), this.weight, this.volume) + " with");
        System.out.println();
        for (int i=0;i<item.size();i++) {
            System.out.print((i+1) + ": ");
            System.out.println(item.get(i));
        }
        System.out.println("Total: ");
    }

I wszystko mi się już nawet wyświetla, ale teraz chciałbym policzyć łączny ciężar i objętość wraz wagą i objętością samego pudełka. Czy to się da jakoś wyciągnąć? Podejrzewam, że z listy to chyba nie, więc pewnie z klasy Thing, ale jak?
Tak sobie myślę, że powinienem wagę i objętość pudełka dołożyć jakoś na początek listy, to wtedy łatwiej byłoby z jednego miejsca wyciągnąć te parametry, Ale na ten moment mam za mało umiejętności. Czy mógłbym prosić o pomoc?

0

W pierwotnym kodzie nie ma klasy `Backpack'. Zmieniłeś nazwę, czy dopisałeś nową klasę?

0
bogdans napisał(a):

W pierwotnym kodzie nie ma klasy `Backpack'. Zmieniłeś nazwę, czy dopisałeś nową klasę?

Oj tak, sejf i plecak to to samo...

0
class Backpack{
...
public double getWeight(){
        double total = 0;
	for (int i=0;i<item.size();i++) {
            total += item.get(i).getWeight();
        }
        return total;
    }
}

W kolekcji masz obiekty typu Thing, które mają gettery: getWeight(), getVolume() więc korzystaj z nich.

0

Może tak:

        double totalWeight = 0.0;
        for (int i=0;i<item.size();i++) {
            System.out.print((i+1) + ": ");
            Thing thing = item.get(i);
            System.out.println(thing);
            totalWeight += thing.weight;
        }
0

@bogdans Czy uważasz, że lepiej odwoływać się do pola czy do gettera? Wg mnie lepiej korzystać z getterów, przykład może naciągany, ale ilustruje tę różnicę:

class Person{
  protected String name;
  public Person(String name){
    this.name = name;
  }

  public Person(){
  }

  public String getName(){
    return name;
  }
}
class Worker extends Person{
  protected char[] name;
  public Worker(char[] name){
    this.name = name;
  }

  public String getName(){
    return new String(name);
  }
}

class Main {
  public static void main(String[] args) {
    Person p = new Worker("Adam".toCharArray());
    System.out.println(p.getName());
    System.out.println(p.name);
  }
}

Efekt:
Adam
null

0
cs napisał(a):

@bogdans Czy uważasz, że lepiej odwoływać się do pola czy do gettera? Wg mnie lepiej korzystać z getterów, przykład może naciągany, ale ilustruje tę różnicę:

class Person{
  protected String name;
  public Person(String name){
    this.name = name;
  }

  public Person(){
  }

  public String getName(){
    return name;
  }
}
class Worker extends Person{
  protected char[] name;
  public Worker(char[] name){
    this.name = name;
  }

  public String getName(){
    return new String(name);
  }
}

class Main {
  public static void main(String[] args) {
    Person p = new Worker("Adam".toCharArray());
    System.out.println(p.getName());
    System.out.println(p.name);
  }
}

Efekt:
Adam
null

Na siłę to można wszystko udowodnić. Ten przykład ma tyle złych praktyk, że nie ma sensu go rozpatrywać. Jednym z sensowniejszych podejść jest zapewnienie niemutowalności danego pola i odwoływanie się bezpośrednio do niego. W każdym innym przypadku wpierw należy zastanowić się czy getter w ogóle jest potrzebny. W ten sposób możesz łatwo ujawnić wewnętrzny stan danego obiektu narażając go na modyfikację z zewnątrz, a tym samym trudne do określenia błędy

0

@DisQ: Obrażasz się na możliwości Javy, nie ja wymyśliłem przykrywanie pól. Wg Ciebie złą praktyką jest robienie pól, które nie są final? Jak w tym przykładzie zmienisz getterem pola name? Była moda na gettery i settery, teraz na bezkrytyczne wciskanie niemutowalności, gdzie tylko się da. Jedno i drugie ma swoje miejsce. Wszyscy patrzą na Jave przez pryzmat webówki, jako jedynie słusznego zastosowania.

0

Daleko mi do obrażania się na Javę. Tak, według mnie jeśli tylko można to powinno się robić pola final - mi to ułatwia pisanie kodu, a co ważniejsze - jego czytanie. W twoim przykładzie po prostu bym nie zmieniał pola name, a tym bardziej nie używałbym do tego celu gettera.

0

@DisQ: @geoinfomat uczy się, jak widać, Javy i działa z dziedziczeniem, więc pokazałem możliwe skutki tego dziedziczenia i różnicę między getterem a odwoływaniem się do pól. Nie korzysta z final, więc może jeszcze tego nie zna, nie przerabiał, trudno wszystko na raz ogarnąć, więc zasymulował niezmienność pola samymi getterami. W kodzie wszystko robi w jednym pliku, w dodatku w tym samym pakiecie, więc i tak te gettery są zbędne. Ale jak skorzysta z klas w innym pakiecie to nie dostanie się do pól, więc lepiej żeby korzystał z utworzonych getterów i pól protected, niż robił publiczne pola bez final.

0

Zdaję sobie sprawę z tego, że rozmowy na tym forum są na znacznie wyższym poziomie. Wszystko uważnie czytam. Dochodzę jednak do wniosku, że bez prób niewiele mi się uda osiągnąć.
Ja dalej jestem na etapie wkładania do sejfu różnych rzeczy.
Włożyłem już do niego nawet kolejny sejf, ale jak wynika z main, powinienem do tego drugiego sejfu włożyć inne przedmioty (te jednak mają nieco inne rozszerzające pola), no i tu mam znowu kłopot, bo jak na razie wychodzi mi bardziej jakiś adres niż liczby.
Próbowałem założyć nową listę, ot przez analogię, ale wciąż gdzieś popełniam błędy.
Do znudzenia proszę o dalszą pomoc (ale naprawdę nad tym siedzę, tylko umysł już nie ten...)
Wydaje mi się, że nie potrafię wykorzystać tej rozszerzającej klasy Box...
PS. Z grzeczności próbuję wykorzystać jeden i drugi pomysł, a kiedyś pewnie się zastanowię, który lepszy.

class Safe {
    double weight;
    double volume;
    double maxWeight;
    double maxVolume;


    public Safe(double weight, double volume, double maxWeight, double maxVolume) {
        this.weight = weight;
        this.volume = volume;
        this.maxWeight = maxWeight;
        this.maxVolume = maxVolume;
    }

    ArrayList<Thing> item = new ArrayList<Thing>();
    ArrayList<Safe> item1 = new ArrayList<Safe>();

    public void add(Thing thing) {
        item.add(thing);
    }

    public void add(Safe small) {
        item.add(new Thing(Safe.class.getSimpleName(), small.weight, small.volume ));
    }

    public void remove(int index) {
        item.remove(index - 1);
    }

    public void printContent() {
        System.out.println(new Thing(Safe.class.getSimpleName(), this.weight, this.volume) + " with");
        double totalWeight = 0.0;
        double totalVolume = 0.0;
        for (int i = 0; i < item.size(); i++) {
            System.out.print((i + 1) + ": ");
            Thing thing = item.get(i);
            System.out.println(thing);
            totalWeight += thing.weight;
            totalVolume += thing.volume;
//            for (int j = 0; j < item1.size(); j++) {
//                System.out.print((j + item1.size() + 1) + ": ");
//                Safe small = item1.get(j);
//                System.out.println(small);
//                totalWeight += small.weight;
//                totalVolume += small.volume;
//            }
        }
        System.out.println("Total: " + (totalWeight + this.weight) + ", " + (totalVolume + this.volume));
        System.out.println();
    }

   public double getWeight() {
        double total = 0.0;
        for (int i = 0; i < item.size(); i++) {
            total += item.get(i).getWeight();
        }
        return total+ this.weight;
    }
}

0

Pomyśl co by Ci dało wyprowadzenie klasy Safe z Thing, wtedy zamiast robić osobną kolekcję na sejfy miałbyś jedną na wszystkie rzeczy, w tym i sejf. Wtedy miałbyś jedną metodę add. Możesz uznać, że na ten moment to wystarczająco "dobre" rozwiązanie", potem jak poznasz interfejsy to zapomnij o tym.

0
cs napisał(a):

Pomyśl co by Ci dało wyprowadzenie klasy Safe z Thing, wtedy zamiast robić osobną kolekcję na sejfy miałbyś jedną na wszystkie rzeczy, w tym i sejf. Wtedy miałbyś jedną metodę add. Możesz uznać, że na ten moment to wystarczająco "dobre" rozwiązanie", potem jak poznasz interfejsy to zapomnij o tym.

To może śmieszne, ale trzy dni mi zajęły próby z tą sugestią i nie wymyśliłem niczego sensownego.
Niestety na ten moment nie potrafię umieścić mniejszego sejfu z całą jego zawartością w większym.
Natomiast potrafię utworzyć dwa osobne sejfy z zawartością, tzn wpisując w funkcji main

b.printContent();
small.printContent();

wyświetla mi się zawartość obu. Niemniej jednak dziękuję Państwu za pomoc. Na razie zabieram się za prostsze rzeczy, żeby później zrozumieć te trudniejsze.
Gdyby jeszcze ktoś zechciał bardziej łopatologicznie mi to wytłumaczyć, to pewnie wrócę do pracy nad tym programem.
Spodziewana zawartość w zadaniu jest taka:
Safe (0.1 kg, 0.5 l) with
1: Ball (1 kg, 3 l)
2: Torch (0.5 kg, 1 l)
3: Box1 (5 kg, 25 l)
Total: 5.6 kg 29.5 l
Safe (0.1 kg, 0.5 l) with
1: Ball (1 kg, 3 l)
2: Box1 (5 kg, 25 l)
Total: 5.1 kg 28.5 l
5.1
Safe (0.1 kg, 0.5 l) with
1: Ball (1 kg, 3 l)
2: Box1 (5 kg, 25 l)
3: Backpack (0.01 kg, 0.1 l) with
1: Box2 (3 g, 8 l)
Total: 3.01 kg, 8.1 l
Total: 5.1 kg 28.5 l

a ja na ten moment mam taką:
Backpack (0.1 kg, 0.5 l) with
1: Ball (1.0 kg, 3.0 l)
2: Torch (0.5 kg, 1.0 l)
3: Box1 (5.0 kg, 25.0 l)
Total: 6.6, 29.5

Backpack (0.1 kg, 0.5 l) with
1: Ball (1.0 kg, 3.0 l)
2: Box1 (5.0 kg, 25.0 l)
Total: 6.1, 28.5

6.1

Backpack (0.1 kg, 0.5 l) with
1: Ball (1.0 kg, 3.0 l)
2: Box1 (5.0 kg, 25.0 l)
3: Backpack (0.01 kg, 0.1 l)
Total: 6.109999999999999, 28.6

Backpack (0.01 kg, 0.1 l) with
1: Box2 (3.0 kg, 8.000000000000002 l)
2: Box3 (1.0 kg, 4.000000000000001 l)
Total: 4.01, 12.100000000000003

0

Dodałem konstruktor w klasie Thing:

   public Thing((Safe small) {
        this.small = small;
    }

i metodę w klasie Safe

void add(Safe small) {

              element.item.add(new Thing(small));
    }

ale zwraca mi zera. Dalej o czymś nie wiem...

1 użytkowników online, w tym zalogowanych: 0, gości: 1