Java - pytanie o korzystanie z metod i widoczność obiektów

0

Cześć, mam pytanie o korzystanie z metod i widoczność obiektów. Jakoś jeszcze tego nie łapię, a pewnie jest to bardzo proste.
Mam taki kod:

    private Integer mainField;

    public static void main(String[] args) {
        Main main = new Main();
        main.start();
    }

    public void start() {
        ClassA classA = new ClassA();
        ClassB classB = new ClassB();

        this.doSthMain();
    }

    public void doSthMain() {
        classA.doSthA();
        classB.doSthB();
    }

    public Integer getMainField() {
        return  mainField;
    }
}



public class ClassA {
    private Integer classAField;

    public Integer getClassAField() {
        return classAField;
    }

    public Integer doSthClassA() {
        Integer clB = 100;
        return clB;
    }

    public void doNothing() {
        Integer z = main.getMainField();
    }
}



public class ClassB {
    private Integer classBField;
    
    public Integer getClassBField() {
        return classBField;
    }
    
    public Integer doSthClassB() {
        Integer clB = classA.doSthClassA() + 5;
        return clB;
    }
}

Wszystkie te 3 klasy sa w jednym pakiecie. Zaczynam od main(), tworze obiekt main i przekazuję strowanie do main.start(). Tam tworze obiekty klas A i B, a następnie przechodzę do main.doSthMain().

Pytanie 1. w tej metodzie nie są widoczne metody classA.doSthA() i classB.doSthB(). Kompilator zgłasza błąd, ze ich nie zna. Dlaczego nie mogę wywołać ich z main.doSthMain() ? Przeciez obiekty utworzyłem. Czy dlatego, że choć były utworzone w tym samym obiekcie, ale innej metodzie? jeśli tak to jak uzyskać do nich dostęp w main.doSthMain()?

Pytanie 2. Załóżmy, ze w main.doSthMain() mogę juz wywołać metody klasy A i B. Wywołując tam classB.doSthB() przechodzę do metody klasy B. Tam jednak kompilator piszczy, że nie ma dostępu (nie widzi) classA.doSthClassA(). Jak z kolei zrobić, żeby classB miała dostęp do classA.doSthA? Czy chodzi o to, że w wywołniach poszczególnych metod muszę przekazywać obiekty w parametrze? Innymi słowy, czy wywołując main.doSthMain() musze jej przekazać classA i classB, a potem do classB.doSthClassB muszę dalej przekazać w parametrze classA, żeby móc coś z A odczytać? Czy też należy zapisać to w inny sposób - jaki? Dziękuję za pomoc.

2

Problemem nie jest widoczność metod tylko zasięg obiektów. To: ClassA classA = new ClassA(); jest ZMIENNA LOKALNA która zniknie po wyjściu z funkcji. W efekcie twoje classA.doSthA(); zgłasza że odnosisz sie do nieistniejącej zmiennej classA.
Myśle że warto zacząć naukę od zrozumienia że KLASA i OBIEKT to są zupełnie różne rzeczy. Klasa określa typ danych a obiekt konkretną rzecz. String jest klasą ale "ala ma kota" i "sierotka ma rysia" to dwa różne obiekty tej klasy.

0

@Shalom: Róźnicę Klasa - obiekt danej klasy rozumiem. Problemem jest właśnie ten zasięg obiektów.

0

To nie sa metody statyczne. Np. nie mozesz zrobic String.replace("a", "b") bo niby na rzecz jakiej instancji klasy String mialoby sie to wykonac?

Natomiast jezeli ta metoda nie zalezy od kontekstu danego obiektu to mozesz sobie zrobic static xxx foobar(...) { i wtedy classX.foobar(...) bedzie dzialac. Dla przykladu statyczna metoda jest Integer.parseInt("42").

Ale jak ta patrze na ten kod z przykladu to dodanie staticow nie wystarczy :)

1

@witek2 no dobra to pacz, weźmy ten twój kod:

public class ClassA {
    private Integer classAField;

    public Integer getClassAField() {
        return classAField;
    }

    public Integer doSthClassA() {
        Integer clB = 100;
        return clB;
    }

    public void doNothing() {
        Integer z = main.getMainField();
    }
}

Masz tu jakieś magiczne main.getMainField(); a moje pytanie brzmi: do jakiego OBIEKTU się to niby odnosi? Co jak zrobie

Main main1 = new Main();
Main main2 = new Main();

I cyk, mam 2 obiekty klasy Main i do którego z nich odnosi się niby to twoje Integer z = main.getMainField(); i na jakiej podstawie?

Popatrzmy też na:

    public void start() {
        ClassA classA = new ClassA();
        ClassB classB = new ClassB();

        this.doSthMain();
    }

    public void doSthMain() {
        classA.doSthA();
        classB.doSthB();
    }

Znów, na jakiej podstawie doSthMain ma wiedzieć do czego się odnoszą te classA? Załóżmy że mamy jakieś

    public void start1() {
        ClassA classA = new ClassA(69);
        ClassB classB = new ClassB(69);

        this.doSthMain();
}
    public void start2() {
        ClassA classA = new ClassA(96);
        ClassB classB = new ClassB(96);

        this.doSthMain();
}

I jak wg ciebie to ma działać teraz kiedy obiektów o takich nazwach "niby" jest więcej?

Nic się samo nie dzieje. Jak chcesz odnosić się do obiektu to musi być w danym zasięgu, więc twoje doSthMain albo musi dostać te obiekty jako argumenty wywołania funkcji tak jak masz np. "alamakota".replace("a","b") -> "a" i "b" są argumentami funkcji!, albo ewentualnie to muszą być pola klasy w której masz te swoje metody.

0

Ok. Przeanalizowałem odpowiedzi, pozmieniałem nieco mój kod, bo rzeczywiście coś w nim pomieszałem, a rezultat zamieszczam.

public class Aplikacja {
    private final Integer aplikacjaField = 5;
    ClassA classA;
    ClassB classB;


    public static void main(String[] args) {
        Aplikacja aplikacja = new Aplikacja();
        aplikacja.start();
    }

    public void start() {
        classA = new ClassA();
        classB = new ClassB();

        this.doSthMain();
    }

    public void doSthMain() {
        classA.doSthClassA();
        Integer result = classB.doSthClassB(classA, aplikacjaField);
        System.out.println(result);
    }

    public Integer getMainField() {
        return  aplikacjaField;
    }
}



public class ClassA {
    private Integer classAField;

    public Integer getClassAField() {
        return classAField;
    }

    public Integer doSthClassA() {
        Integer clA = 100;
        return clA;
    }

    public Integer doNothing(Integer mainField) {
        Integer z = mainField;
        return z;
    }
}




public class ClassB {
    private Integer classBField;
    
    public Integer getClassBField() {
        return classBField;
    }
    
    public Integer doSthClassB(ClassA classA, Integer aplikacjaField) {
        Integer clB = classA.doSthClassA() + 5;
        Integer xxx = classA.doNothing(aplikacjaField);
        return xxx +1;
    }
}

Dla przejrzystości nazwę klasy Main zamieniłem na Apliakcja. Kompilator nie ma uwag. Wynik to 6. Deklaracje klas A i B wrzuciłem jako pola w klasie Aplikacja. Teraz klasy te sa dostępne dla każdej metody klasy Aplikacja. Z kolei w linii: Integer result = classB.doSthClassB(classA, aplikacjaField) przekazuję do classB referencję do classA (bo jak rozumiem classB nic nie wie o istnieniu classA) i teraz może ona (classB) skorzystać z jej metody (classA). Czy taki zapis i przekazywanie referencji do obiektów jest prawidłowy? Czy tak to się własnie robi, czy tez jest może inny, bardziej właściwy sposób?

1

Deklaracje klas A i B wrzuciłem jako pola w klasie Aplikacja.

Tak jak pisałem, nadal nie rozumiesz. To są OBIEKTY klas A i B.

Czy taki zapis i przekazywanie referencji do obiektów jest prawidłowy?

Oczywiście że tak. Jak chcesz dodać dwa inty to jak to robisz? Przekazujesz do funkcji dodającej dwa obiekty które chcesz dodać.

0

@Shalom: Dziękuję.

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