Liczba instancji klasy zagniezdzonej

0
         public class TreeList
        {
            private int mainitemsCount;

            public class MainItem
            {
                private string title;

                public string Title
                {
                    set { this.title = value; }
                    get { return title; }
                }

                public MainItem()
                {
                    //z tego miejca chce zwiekszyc pole mainItemsCounts, (mainItemsCounts++)
                    // title="MainItem"+mainItemsCounts.ToString();
                }
            }

Lecz nie moge sie dostac do pola mainItemsCounts z wskazanego miejsca, wdaczego?

0

Albowiem próbujesz się dostać do prywatnego składnika innej klasy. Nie pomaga tutaj, że miejsce, o którym mówisz należy do klasy zagnieżdżonej - inna klasa to inna klasa i wara od prywatnych składników.

0

no tak, nie dalem calego przykladu, w oryginale uzylem wlasciwosci, i tez nie idzie

        public class TreeList
        {
            private int mainitemsCount;

            public class MainItem
            {
                private string title;

                public string Title
                {
                    set { this.title = value; }
                    get { return title; }
                }

                public MainItem()
                {
                    //z tego miejca chce zwiekszyc pole mainItemsCounts, (mainItemsCounts++)
                    // title="MainItem"+ MainItemCount.ToString();
                }
            }
            public int MainItemCount
            {
                get { return mainItemCount; }
            }
       }
0

mainitemCounts jest polem prywatnym klasy TreeList.

MainItemCount jest właściwością tylko do odczytu klasy TreeList.

Więc jakim cudem chcesz zmienić wartość tego pola z zupełnie innej klasy MainItem?
Dodaj akcesor set do właściwości, albo zmień dostęp pola na internal bądź public.

P.S. Po co zagnieżdżasz klasy?

0

Albowiem będąc w klasie możesz odwołać się do składnika innej (tutaj nadrzędnej) klasy tylko przez konkretną instancję typu - obiekt. Wyjątkiem są składniki statyczne, które istnieją niezależnie od instancji.

Jeśli to jest niezrozumiałe, to przeanalizuj kawałek kodu

... // załóżmy, że TreeList.MainItemCount ma zarówno get jak i set

TreeList tl1 = new TreeList();
tl1.MainItemCount = 1;

TreeList tl2 = new TreeList();
tl2.MainItemCount = 2;

TreeList.MainItem mi = new TreeList.MainItem();
...

Jaka liczba Twoim zdaniem powinna być odczytana w konstruktorze w zmiennej mi ?

0
Hass napisał(a)

Albowiem będąc w klasie możesz odwołać się do składnika innej (tutaj nadrzędnej) klasy tylko przez konkretną instancję typu - obiekt. Wyjątkiem są składniki statyczne, które istnieją niezależnie od instancji.

Jeśli to jest niezrozumiałe, to przeanalizuj kawałek kodu

... // załóżmy, że TreeList.MainItemCount ma zarówno get jak i set

TreeList tl1 = new TreeList();
tl1.MainItemCount = 1;

TreeList tl2 = new TreeList();
tl2.MainItemCount = 2;

TreeList.MainItem mi = new TreeList.MainItem();
...

Jaka liczba Twoim zdaniem powinna być odczytana w konstruktorze w zmiennej mi ?

Zadna, skoro nawet przy uzyciu akcesorw get i set nie moge sie dostac do wlasciwosci MainItemscount, proba inkrementacki wygereruje blad kompilatora z powodu braku dostepu ;)

0

Dokładnie. A chciałbyś, żeby co się stało?

0

Czyli nie ma mozliwośći dostania sie do zmiennej w sposob jaki chcialem to zrobic w poscie pierwszym? A metoda na obejscie tego?

0

Mówiąc krótko - C# to nie Java. Nie wszystko w C# musi być identyczne jak w Javie.
W Javie bez problemu dostaniesz się z wewnętrznej klasy do prywatnej zmiennej klasy zewnętrznej, natomiast w C# wpierw musisz stworzyć instancję klasy zewnętrznej, a dopiero później będziesz mógł się dostać do wszystkich zmiennych (nawet prywatnych) tej klasy.
W konstruktorze klasy wewnętrznej MainItem wpisz wpierw:
TreeList tl = new TreeList();
I dopiero teraz będziesz mógł dostać się do zmiennych prywatnych klasy TreeList:
tl.mainitemsCount++

Jak już wcześniej wspomniałem C# to nie Java choć oba języki mają wiele wspólnych cech. W Javie nie można przeciążać operatorów, a w C# można. W Javie i w C# można dziedziczyć tylko po jednej klasie i implementować wiele interfejsów. Natomiast dostęp do zmiennych klasy zewnętrznej z klasy wewnętrznej w obu językach jest inny.
Ciekawą właściwością języka C# są klasy częściowe. Polega to na tym, że jedną klasę można zdefiniować w kilku plikach. Więcej informacji znajdziesz tutaj:
link
Ten mechanizm jest stosowany w ASP.NET.
W Javie z czymś takim się nie spotkałem.

0
Igor1981 napisał(a)

Mówiąc krótko - C# to nie Java. Nie wszystko w C# musi być identyczne jak w Javie.
W Javie bez problemu dostaniesz się z wewnętrznej klasy do prywatnej zmiennej klasy zewnętrznej, natomiast w C# wpierw musisz stworzyć instancję klasy zewnętrznej, a dopiero później będziesz mógł się dostać do wszystkich zmiennych (nawet prywatnych) tej klasy.
W konstruktorze klasy wewnętrznej MainItem wpisz wpierw:
TreeList tl = new TreeList();
I dopiero teraz będziesz mógł dostać się do zmiennych prywatnych klasy TreeList:
tl.mainitemsCount++

Jak już wcześniej wspomniałem C# to nie Java choć oba języki mają wiele wspólnych cech. W Javie nie można przeciążać operatorów, a w C# można. W Javie i w C# można dziedziczyć tylko po jednej klasie i implementować wiele interfejsów. Natomiast dostęp do zmiennych klasy zewnętrznej z klasy wewnętrznej w obu językach jest inny.
Ciekawą właściwością języka C# są klasy częściowe. Polega to na tym, że jedną klasę można zdefiniować w kilku plikach. Więcej informacji znajdziesz tutaj:
link
Ten mechanizm jest stosowany w ASP.NET.
W Javie z czymś takim się nie spotkałem.

Ale ja nie chce tworzyc obiektow TreeList przy kazdorazowym zuyciu konstruktora MainItem();

0
Piotru napisał(a)

Ale ja nie chce tworzyc obiektow TreeList przy kazdorazowym zuyciu konstruktora MainItem();

Nie masz innego wyjścia. W Javie są klasy wewnętrzne (inner classes), natomiast w C# podobnie jak w C++, są klasy zagnieżdżone (nested classes). W C# możesz uzyskać dostęp do tej zmiennej tylko w taki sposób jaki Ci pokazałem wcześniej.
Jak znasz angielski, to poczytaj sobie:
C# nested classes are like C++ nested classes, not Java inner classes

0
Igor1981 napisał(a)
Piotru napisał(a)

Ale ja nie chce tworzyc obiektow TreeList przy kazdorazowym zuyciu konstruktora MainItem();

Nie masz innego wyjścia. W Javie są klasy wewnętrzne (inner classes), natomiast w C# podobnie jak w C++, są klasy zagnieżdżone (nested classes). W C# możesz uzyskać dostęp do tej zmiennej tylko w taki sposób jaki Ci pokazałem wcześniej.
Jak znasz angielski, to poczytaj sobie:
C# nested classes are like C++ nested classes, not Java inner classes

public class TreeList
        {
            private int mainitemsCount;

            public class MainItem
            {
                private string title;
                public static int MainNodesCount = 0;   //<-----------

                public string Title
                {
                    set { this.title = value; }
                    get { return title; }
                }
                public int MainItemCount
                {
                     get { return mainItemCount; }
                }


                public MainItem()
                {
                   MainItemCount++; //<-----------
                }
            }

       } 

static i po problemie ;p

0
piotrsh napisał(a)

static i po problemie ;p

Nie bardzo. Spróbuj w jednym programie postawić dwie takie "kontrolki".

Nie łatwiej po prostu przekazać (np. w konstruktorze) obiekt nadrzędny do obiektu zagnieżdżonego?

0
piotrsh napisał(a)

static i po problemie ;p

Ehhh... to trzeba było od razu napisać, że jest Ci potrzebny licznik instancji obiektów MainItem. Przedstawiłeś w niejasny sposób swój problem i pewnie nikt nie zrozumiał o co Ci chodzi.

0
Igor1981 napisał(a)
piotrsh napisał(a)

static i po problemie ;p

Ehhh... to trzeba było od razu napisać, że jest Ci potrzebny licznik instancji obiektów MainItem. Przedstawiłeś w niejasny sposób swój problem i pewnie nikt nie zrozumiał o co Ci chodzi.

A przeczytaj temat ;)

0

Ten static nie rozwiązuje problemu.
Odpowiedz sobie na pytania, które pominąłeś w rozumowaniu:
Do którego TreeList ma należeć MainItem podczas jego tworzenia?

Powiązanie TreeList z MainItem (razem z inkrementacją mainitemsCount) możesz wykonać:

  • Przekazując macierzysty TreeList do publicznego MainItem w publicznym konstruktorze.
  • Wyposażając klasę TreeList i/lub MainItem w publiczną metodę pozwalającą powiązać jeden z drugim.
  • Tylko klasie TreeList pozwolić na tworzenie instancji MainItem (oznaczając klasę MainItem jako private/protected która jedynie dziedziczy po publicznym interfejsie/klasie), a powiązanie wykonać podczas tworzenia przekazując macierzysty TreeList w konstruktorze.
0
peterek napisał(a)
Igor1981 napisał(a)
piotrsh napisał(a)

static i po problemie ;p

Ehhh... to trzeba było od razu napisać, że jest Ci potrzebny licznik instancji obiektów MainItem. Przedstawiłeś w niejasny sposób swój problem i pewnie nikt nie zrozumiał o co Ci chodzi.

A przeczytaj temat ;)

Ten temat powinien być w dziale Newbie. Żadnemu doświadczonemu programiście nawet nie przyjdzie do głowy, że ktoś może nie wiedzieć, że do zliczania instancji obiektów należy wykorzystać zmienną static, no chyba że taki temat znajduje się w dziale Newbie. I wtedy są nieporozumienia i odpowiedzi nie na temat tak jak w tym temacie.

0
Igor1981 napisał(a)
peterek napisał(a)
Igor1981 napisał(a)
piotrsh napisał(a)

static i po problemie ;p

Ehhh... to trzeba było od razu napisać, że jest Ci potrzebny licznik instancji obiektów MainItem. Przedstawiłeś w niejasny sposób swój problem i pewnie nikt nie zrozumiał o co Ci chodzi.

A przeczytaj temat ;)

Ten temat powinien być w dziale Newbie. Żadnemu doświadczonemu programiście nawet nie przyjdzie do głowy, że ktoś może nie wiedzieć, że do zliczania instancji obiektów należy wykorzystać zmienną static, no chyba że taki temat znajduje się w dziale Newbie. I wtedy są nieporozumienia i odpowiedzi nie na temat tak jak w tym temacie.

Tak, tylko problem jest bardziej skomplikowany, poniewaz chce aby to klasa TreeList posiadala informacje o ilosci utworzonych elementow klasy MainItem. Lecz tego problemu nie potrafilsmy rozwiazac, więc musze obejsc sie zmakiem i kombinowac.

0
piotrosh napisał(a)

Tak, tylko problem jest bardziej skomplikowany, poniewaz chce aby to klasa TreeList posiadala informacje o ilosci utworzonych elementow klasy MainItem. Lecz tego problemu nie potrafilsmy rozwiazac, więc musze obejsc sie zmakiem i kombinowac.

Nie bardzo rozumiem. Przecież jak w klasie TreeList umieścisz zmienną:

private static int mainitemsCount;

i będziesz ją zwiększał w konstruktorze MainItem:

mainitemsCount++;

to klasa TreeList będzie posiadała informację o ilości instancji obiektów MainItem.
W czym więc problem?

0
Igor1981 napisał(a)
piotrosh napisał(a)

Tak, tylko problem jest bardziej skomplikowany, poniewaz chce aby to klasa TreeList posiadala informacje o ilosci utworzonych elementow klasy MainItem. Lecz tego problemu nie potrafilsmy rozwiazac, więc musze obejsc sie zmakiem i kombinowac.

Nie bardzo rozumiem. Przecież jak w klasie TreeList umieścisz zmienną:

private static int mainitemsCount;

i będziesz ją zwiększał w konstruktorze MainItem:

mainitemsCount++;

to klasa TreeList będzie posiadała informację o ilości instancji obiektów MainItem.
W czym więc problem?

No ze static da rade, ale glowilismy sie jak to zrobic bez ;p

0

Poniewaz przy uzyciu wiecej niz 1 obiektu TreeList static staje sie bezuzyteczne

0
peterq napisał(a)

Poniewaz przy uzyciu wiecej niz 1 obiektu TreeList static staje sie bezuzyteczne

A czy ta klasa MainItem koniecznie musi być zagnieżdżoną klasą w klasie TreeList?
Może lepiej byłoby w klasie TreeList umieścić jakiś prywatny kontener przechowujący obiekty MainItem, stworzyć specjalną metodę za pomocą której będziesz tworzył obiekty MainItem i która od razu wrzuci obiekt MainItem do kontenera? W takim przypadku nie będziesz miał żadnego problemu z obliczeniem ilości obiektów MainItem znajdujących się w danym obiekcie TreeList.

0

Chcialem zdefiniowac TreeList jako samodzienla klase operujaca na elementach MainItem i Item. Wiec zagniezdzilem klase aby uczynic ja bardziej "przenosna". Nie znam wad i zalet zagniezdzen, wiec pomysl moze byc bezsensowny.

0
petrq napisał(a)

Chcialem zdefiniowac TreeList jako samodzienla klase operujaca na elementach MainItem i Item. Wiec zagniezdzilem klase aby uczynic ja bardziej "przenosna".

W takim razie możesz stworzyć dwie definicje klas (klasa TreeList i klasa MainItem) w jednym pliku.
Możesz też stworzyć definicję klasy TreeList, a w niej zagnieżdżoną klasę MainItem. Klasa MainItem może być zdefiniowana jako private lub jako public. Jeśli będzie jako public, to będzie do niej dostęp za pomocą składni:

TreeList.MainItem klasa = new TreeList.MainItem();

Będzie można tak się dostać do niej z dowolnej części programu, który będzie dołączał Twoją bibliotekę za pomocą using.
Możesz też zdefiniować zagnieżdżoną klasę MainItem jako private. Wtedy tylko z TreeList będzie możliwy dostęp do niej.
Jeśli zdefiniujesz klasę MainItem jako zagnieżdżoną w klasie TreeList, to bez względu na to czy będzie ona prywatna czy publiczna, możesz utworzyć w klasie TreeList obiekt MainItem:

public class TreeList
{
    private MainItem jedenObiektMainItem;
    private MainItem[] tablicaObiektowMainItem;
    private List<MainItem> kontenerObiektowMainItem;

    public void metodaOperujacaNaMainItem()
    {
        // Jakiś kod
    }

    private class MainItem
    {
    }
}

W tym przypadku możesz stworzyć w klasie TreeList specjalne metody odpowiedzialne za tworzenie i modyfikację obiektów MainItem, które będą publicznie dostępne.
W takim przypadku nie będziesz miał żadnego problemu z policzeniem ilości obiektów MainItem znajdujących się w danym obiekcie TreeList.

0

ok, dzieki za poswiecony czas, musze pomyslec co mi sie najbradziej przyda.

0

naprawde nie macie co rozstrzasac..? zeby operowac na nie-statycznych polach obiektu X, inny obiekt Z musi posiadac chocby na moment referencje do X i kropka. podstawy OO sie klaniaja.

public class TreeList
{
    private int mainitemsCount;

    public MainItem CreateMainItem(){ return new MainItem(this); }

    public class MainItem
    {
        public string Title {get; set; } //btw. od kawalka czasu tak mozna zaimplementowac proste property

        public MainItem(TreeList parent)
        {
            (_parent=parent).mainitemsCount++;    // nested-class ma dostep do private swojej containg-class
        }

        private TreeList _parent; //parent zapamietany tylko na potrzeby --
        public dispose/finalize/itd itp
        {
            _parent.mainitemsCount--;
        }
    }
}

jak sie nie podoba konstruktor parametrowy, uzywaj CreateMainItem z jakiejs instancji obiektu klasy TreeView..

a tak na boku, nie wiem po co komu taka funkcjonalnosc.. wrzucaj predzej te MainItem do jakiejs kolekcji w TreeView i pytaj kolekcje o Counta.. roboty i nerwow sobie oszczedzisz

public class TreeList
{
    private List<MainItem> items;
    
    public MainItem CreateMainItem()
    {  var newitem = new MainItem();
        items.add(newitem);
        return newitem;
    }
    public void ReleaseMainItem(MainItem  item)   //ew. mozna pomyslec o jakims MainItem:IDisposable i .Dispose+=...
    {  items.Remove(item);
    }

    private int liczbaMainItem { get{return items.Count; } }

    public class MainItem
    {
        public string Title {get; set; }
        ....
    }
}

//edit: heh, nie potrzebnie wychodzilem na herbate po przeczytaniu watku.. zdazyl urosnac o pare nowych postow..

a co do zalet/wad nestedclass:

  • wada: trzeba zawsze ja nazywac wraz z klasa otaczajaca, zaden using nie pomaga, musisz pisac: OuterClass.NestedClass
  • wada: nestedclass'a bedzie faktycznie sie nazywala: TreeView+MainItem. jesli opierasz cos na reflection, Twoje cos moze nie lubic tego plusa
  • zaleta: nestedclass ma gwarantowany dostep do wszystkich protected/private OuterClass'y, czasem to sie przydaje
  • zaleta: nestedclass moze byc protected/private i przez to widoczna dla mniejszej rzeszy, mozna ich sobie zrobic gazillion i nie beda smiecic w namespace'ie

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