Skocz do zawartości
michalaf

JAVA/C# Jak w klasie przechować "obiekt obiektu"?

Rekomendowane odpowiedzi

Programuję w JAVIE i C#,  nie wiem jak zrobić coś takiego. Tworzę nową klasę, chcę w niej przechować dane typu string, int oraz listę;

public class Osoba {

    public String imię, nazwisko;
    public int wiek;
    
    static public List<Osoba> listaOsób = new ArrayList<Osoba>();

}

W kodzie aplikacji Forms tworzę nowy obiekt typu "Osoba"


        Osoba Pierwsza_Osoba = new Osoba();
        
        Pierwsza_Osoba.imię="Marek";
        Pierwsza_Osoba.nazwisko="Nowak";
		Pierwsza_Osoba.wiek="25";

Teraz chciałbym zrobić coś takiego, np. bym mógł w kodzie odwołać się mniej więcej w ten sposób: 

		Pierwsza_Osoba.Marek.Przychody_Miesięczne = 3200;

Chodzi o to, by po zdefiniowaniu "Marka", później mógłbym się odwołać do tego konkretnego obiektu i wsadzić jeszcze do niego nowy obiekt, coś jak obiekt obiektu :P

Niestety nie wiem jak to profesjonalnie nazwać dlatego nie mogę znaleźć tego w necie, w poradnikach o klasach tego też nie ma.

Czy w ogóle to możliwe? Mam takie zadanie, trochę bardziej skomplikowane więc kod zmieniłem na potrzebę tego komentarza.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

To Java czy C#? W Javie możesz ustawić pole setterem, albo lepiej od razu przez konstruktor. C# ma chyba tak zwane propercje i pełnią one rolę javowych setterów/getterów. Natomiast posiadanie pola Osoba w Osobie nie ma sensu i prawdopodobnie się za coś po prostu źle zabierasz. Napisz lepiej, co chcesz zrobić.

Edytowane przez Karister
  • Upvote 1

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Niestety podałeś za mało informacji. Przykładowo do czego potrzebna jest ci ta lista. W ten sposób można by było stwierdzić czy podszedłeś do tego problemu w dobry sposób, a jeśli nie to jak go rozwiązać.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach
 

W ten sposób można by było stwierdzić czy podszedłeś do tego problemu w dobry sposób

Powiem szczerze, że z czystej ciekawości próbuję wymyślić sensowny przypadek i nie potrafię znaleźć zastosowania listy osób w osobie. Chyba że ciąża mnoga. :D

Edytowane przez Karister

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Najlepiej JAVA bo trudniej mi jest w niej programować. Wiem, za mało informacji bo nie wiedziałem w sumie jak to opisać. Ale już załatwiłem problem.

Stworzyłem dwie klasy, w drugiej stworzyłem obiekt pierwszej. To co opisywałem bardziej wskazywało na dziedziczenie przez klasę ale ostatecznie nie jest to potrzebne.

 

Czy mogę pod tym tematem jeszcze zadać jedno pytanie odnośnie tego samego kodu ale trochę innej sytuacji?
Tworzę jComboBox1 i dodaję w jego properties > model nowe opcje np. opcja1, opcja2, opcja3

Teraz jak mam zrobić w kodzie aplikacji by po wybraniu pierwszej opcji wykonała się pętla

Chodzi o to jak to zrobić w JAVIE, bo w C# robiłem tak:

if (comboBox1.SelectedIndex == 0)
{
	//jakaś operacja, którą chcę wykonać, gdy zaznaczona będzie opcja1

}

 

 

Powiem szczerze, że z czystej ciekawości próbuję wymyślić sensowny przypadek i nie potrafię znaleźć zastosowania listy osób w osobie. Chyba że ciąża mnoga. :D

Kod jest trochę skomplikowany więc wolałem dać prostszy przykład, niekoniecznie logiczny :D Przepraszam

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Nie znam Swinga (używałem na studiach 10 lat temu ostatnio), ale idea będzie taka, że pod JComboBox trzeba podpiąć jakiś ActionListener i on będzie implementował metodę w stylu actionPerformed(ActionEvent e), w której robisz to, co chcesz.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Jeszcze czegoś podobnego nie robiłem więc nie mam pomysłu jak się za to zabrać? Nie dałoby się tak prosto jak w C#?

Ewentualnie ma ktoś pomysł by to łatwo wykonać za pomocą czegoś innego np checkboxa? (Ale wydaje mi się że combobox jest bardziej profesjonalny)

Tzn zrobić jakąś pętle dla wybranej opcji. Póki co umiem w jTable ale nie o to mi teraz chodzi, bo w tej apce to nie będzie dobrze wyglądało

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Ale tu nie ma nic trudnego. Nawet tego Ifa nie trzeba do najprostszego użycia typu wyświetlanie. Tak klasycznie - W Google szukałeś? Po wpisaniu "JComboBox tutorial" znalezienie przykładu zajęło mi 15 sekund: https://www.codejava.net/java-se/swing/jcombobox-basic-tutorial-and-examples.

Edytowane przez Karister

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach
 

Jeszcze czegoś podobnego nie robiłem więc nie mam pomysłu jak się za to zabrać? Nie dałoby się tak prosto jak w C#?

Od przeczytania jak się takie rzeczy robi ;)
Co to znaczy tak prosto jak w C#? Takiego if-a możesz zrobić identycznie.

Proponuję na wstępie ogarnąć trochę Swinga czy czego tam używasz, zapoznać się w jaki sposób działa.
Przechodząc z aplikacji konsolowych może na początku być trudno pewne rzeczy zrozumieć. Przede wszystkim nie pisze się samemu pętli głównej, to załatwiają biblioteki/frameworki od okienek, wywołujesz uruchomienie głównego okna i pewne rzeczy zaczynają się dziać w tle.

Ogólnie tego typu rzeczy działają na zasadzie nasłuchiwania pojawienia się akcji danego elementu okna. Np. przycisk może mieć akcje najechania myszką, wciśnięcia i puszczenia, do każdej z tych akcji można podpiąć inną reakcję. Jak się  nie podepnie, to nie będzie żadnej reakcji na daną akcję.
Nie trzeba przejmować się jak złapać taką akcję, wywołać jej obsługę, to robi za ciebie framework.

  • Upvote 1

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach
Napisano (edytowane)

Może coś w tym stylu dla c#:

 

    class Osoba
    {
        private static ExpandoObject _osoby { get; } = new ExpandoObject();
        public string Imie { get; set; }
        public int Wiek { get; set; }
        public dynamic Osoby => _osoby;

        public Osoba(string imie, int wiek)
        {
            Imie = imie;
            Wiek = wiek;
            ((IDictionary<String, Object>) _osoby)[imie] = this;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var osobaMain = new Osoba("Hehe", 102);
            for (int i = 0; i < 5; i++)
            {
                new Osoba($"Stefan{i}", i);
            }
			
            Console.WriteLine($"Imie: {osobaMain.Osoby.Hehe.Imie}, Wiek:{osobaMain.Osoby.Hehe.Wiek}");
            Console.WriteLine($"Imie: {osobaMain.Osoby.Stefan0.Imie}, Wiek:{osobaMain.Osoby.Stefan0.Wiek}");
            Console.WriteLine($"Imie: {osobaMain.Osoby.Stefan1.Imie}, Wiek:{osobaMain.Osoby.Stefan1.Wiek}");
            Console.WriteLine($"Imie: {osobaMain.Osoby.Stefan2.Imie}, Wiek:{osobaMain.Osoby.Stefan2.Wiek}");
            Console.WriteLine($"Imie: {osobaMain.Osoby.Stefan3.Imie}, Wiek:{osobaMain.Osoby.Stefan3.Wiek}");
            Console.WriteLine($"Imie: {osobaMain.Osoby.Stefan4.Imie}, Wiek:{osobaMain.Osoby.Stefan4.Wiek}");

            Console.ReadLine();
        }
    }

 

Edytowane przez NieUmiemProgramowac

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach
14 godzin temu, NieUmiemProgramowac napisał:

Może coś w tym stylu dla c#:

 


    class Osoba
    {
        private static ExpandoObject _osoby { get; } = new ExpandoObject();
        public string Imie { get; set; }
        public int Wiek { get; set; }
        public dynamic Osoby => _osoby;

        public Osoba(string imie, int wiek)
        {
            Imie = imie;
            Wiek = wiek;
            ((IDictionary<String, Object>) _osoby)[imie] = this;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var osobaMain = new Osoba("Hehe", 102);
            for (int i = 0; i < 5; i++)
            {
                new Osoba($"Stefan{i}", i);
            }
			
            Console.WriteLine($"Imie: {osobaMain.Osoby.Hehe.Imie}, Wiek:{osobaMain.Osoby.Hehe.Wiek}");
            Console.WriteLine($"Imie: {osobaMain.Osoby.Stefan0.Imie}, Wiek:{osobaMain.Osoby.Stefan0.Wiek}");
            Console.WriteLine($"Imie: {osobaMain.Osoby.Stefan1.Imie}, Wiek:{osobaMain.Osoby.Stefan1.Wiek}");
            Console.WriteLine($"Imie: {osobaMain.Osoby.Stefan2.Imie}, Wiek:{osobaMain.Osoby.Stefan2.Wiek}");
            Console.WriteLine($"Imie: {osobaMain.Osoby.Stefan3.Imie}, Wiek:{osobaMain.Osoby.Stefan3.Wiek}");
            Console.WriteLine($"Imie: {osobaMain.Osoby.Stefan4.Imie}, Wiek:{osobaMain.Osoby.Stefan4.Wiek}");

            Console.ReadLine();
        }
    }

 

Mnie to wygląda na anty wzorzec, nie mówiąc o tym, że dla osoby nie znającej C# to wprowadzi więcej zamieszania niż przyniesie pożytku

  • Upvote 1

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach
W dniu 14.05.2021 o 06:37, NieUmiemProgramowac napisał:

Oczywiście, że to anty wzorzec, pytanie było czy mozna i jak coś takiego zrobić.

Choćby tak:

    class Osoba
    {
        public string Imie { get; set; }
        public int Wiek { get; set; }
        public Dictionary<string, Osoba> Osoby { get; protected set; }

        public Osoba(string imie, int wiek)
        {
            Imie = imie;
            Wiek = wiek;
        }

        public static Tuple<Osoba, Dictionary<string, Osoba>> CreateOsoba(string imie, int wiek, Dictionary<string, Osoba> osoby)
        {
            var osoba = new Osoba(imie, wiek);
            //używa kolekcji podanych osób jako źródło, lub tworzy nową
            osoba.Osoby = (osoby != null) ? new Dictionary<string, Osoba>(osoby) : new Dictionary<string, Osoba>();
            osoba.Osoby.Add(imie, osoba); //dodaje najnowsza osobe
            return Tuple.Create(osoba, osoba.Osoby);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");

            var osobaWrapper = Osoba.CreateOsoba("jan", 30, null);
            var osoba = osobaWrapper.Item1;
            var listaOsob = osobaWrapper.Item2;
        }
    }

Albo jeszcze prościej:

    class Osoba
    {
        public static Dictionary<string, Osoba> Osoby { get; protected set; }

        static Osoba()
        {
            Osoby = new Dictionary<string, Osoba>();
        }

        public string Imie { get; set; }
        public int Wiek { get; set; }
        
        public IReadOnlyDictionary<string, Osoba> osoby;

        public Osoba(string imie, int wiek)
        {
            Imie = imie;
            Wiek = wiek;

            osoby = new ReadOnlyDictionary<string, Osoba>(Osoba.Osoby);

            Osoby.Add(imie, this);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var osobaJan = new Osoba("jan", 30);
            var osobaPawel = new Osoba("pawel", 33);
            var osobaMateusz = new Osoba("mateusz", 22);

            Console.WriteLine("wiek mateusza (pytama o to jana): " + osobaJan.osoby["mateusz"].Wiek);
        }
    }

W obu przypadkach kod jest czytelniejszy a błędy łatwiejsze do ustalenia i spora ich część będzie widoczna na etapie kompilacji.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Dla mnie to nadal nie ma sensu. Nie wiem co dokładnie planuje zrobić OP, ale wydaje mi się że zabiera się za to od złej strony.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach
Napisano (edytowane)

@Matt91111

robisz to samo co ja tylko piszesz więcej kodu bo ExpandoObject to tak naprawde dictionary ;) No i nie odwołujesz sie do obiektu innych osób tak osoba.osoby.Mariusz tylko osoba.osoby["Mariusz"], a OP chciał inaczej.

A Tuple można deklarować też tak:

public static (Osoba osoba, Dictionary<string, Osoba> dict) CreateOsoba(string imie, int wiek, Dictionary<string, Osoba> osoby)

i wtedy nie musisz się odwoływać poprzez Item1, Item2 itp tylko zwyczajnie osoba i dict

a jak chcesz stworzyc tupla to tak:
 

var t = (osoba:osoba, dict:osoba.Osoby);

 

I czemu robisz protected na setterze? Przecież nic nie dziedziczysz. I chyba ta properta powinna być private a nie public nie? Nie używasz jej nigdzie na zewnatrz

public static Dictionary<string, Osoba> Osoby { get; protected set; }

Do tego używasz metody Add z dictionary, co jeśli ktoś stworzy dwie osoby o tym samym imieniu? Podpowiem: ArgumentException

 

Do tego tak sie nie robi

Console.WriteLine("wiek mateusza (pytama o to jana): " + osobaJan.osoby["mateusz"].Wiek);

użyj albo string.Format (które jest już przestarzałe) albo najlepiej po nowemu $"tekst w stringu {nazwaZmiennejZTekstem}"

Edytowane przez NieUmiemProgramowac

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach
W dniu 19.05.2021 o 06:54, NieUmiemProgramowac napisał:

@Matt91111

robisz to samo co ja tylko piszesz więcej kodu bo ExpandoObject to tak naprawde dictionary ;) No i nie odwołujesz sie do obiektu innych osób tak osoba.osoby.Mariusz tylko osoba.osoby["Mariusz"], a OP chciał inaczej.

 

Zgadza się, tylko, że taka implementacja jest pozbawiona sensu, nieczytelna  i błędy wyjdą na wierzch dopiero w trakcie działania programu, co szczególnie dla osoby początkującej może być problematyczne.

 

Cytat

I czemu robisz protected na setterze? Przecież nic nie dziedziczysz. I chyba ta properta powinna być private a nie public nie? Nie używasz jej nigdzie na zewnatrz

Rozpędziłem się, o ile dobrze pamiętam to zrobiłem copy/paste z poprzedniego przykładku

Cytat

Do tego używasz metody Add z dictionary, co jeśli ktoś stworzy dwie osoby o tym samym imieniu? Podpowiem: ArgumentException

Wypadało by zacząć od tego, że klucz Dictionary powinien wskazywać na unikalną wartość, którą na pewno nie jest imię, wypadało by użyć tutaj np. numeru pesel/jakiegokolwiek unikalnego id osoby, bazowałem na kodzie z twojego przykładu, aby pokazać inną możliwość implementacji.

Cytat

użyj albo string.Format (które jest już przestarzałe) albo najlepiej po nowemu $"tekst w stringu {nazwaZmiennejZTekstem}"

Zgadzam, się nie mniej uważam, że na potrzeby przykładu nie ma to znaczenia.

 

Z "Tuplami" spoko sprawa, za pewne będę używał ich teraz w ten sposób :)

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Jeśli chcesz dodać odpowiedź, zaloguj się lub zarejestruj nowe konto

Jedynie zarejestrowani użytkownicy mogą komentować zawartość tej strony.

Zarejestruj nowe konto

Załóż nowe konto. To bardzo proste!

Zarejestruj się

Zaloguj się

Posiadasz już konto? Zaloguj się poniżej.

Zaloguj się

  • Ostatnio przeglądający   0 użytkowników

    Brak zarejestrowanych użytkowników przeglądających tę stronę.

×
×
  • Dodaj nową pozycję...