Laden...

Nested Classes: Außere Klasse soll auf sonst unzugängliche Member von innerer zugreifen können

Erstellt von Kuehner vor 14 Jahren Letzter Beitrag vor 14 Jahren 1.668 Views
K
Kuehner Themenstarter:in
489 Beiträge seit 2006
vor 14 Jahren
Nested Classes: Außere Klasse soll auf sonst unzugängliche Member von innerer zugreifen können

Hallo,

Vielleicht schon lange her, dass ich es gebraucht habe:

Angenommen wir haben folgendes:


public class KlassenTante
{
    public class KlassenOnkel
    {
        int test;

        public void AddTest(int value)
        {
            test += value;
        }

        public int Test
        {
            get
            {
                return test;
            }
        }
    }
    
    public KlassenOnkel GibOnkel()
    {
        KlassenOnkel ko = new KlassenOnkel();
        ko.AddTest(1);
        ko.AddTest(2);
        ko.AddTest(3);
        return ko;
    }
}

Nun möchte ich in einer anderen Klasse folgende Funktion aufrufen:


KlassenTante ka = new KlassenTante();
KlassenTante.KlassenOnkel ko = ka.GetOnkel();

Dabei möchte ich jedoch NICHT, dass man nun ko.AddTest(xxx) aufrufen kann, sondern NUR ko.Test.

Wie kann ich die Funktion AddTest schützen? Wenn ich protected mache, kann die KlassenTante auch nicht mehr auf AddTest zugreifen.

Geht das überhaupt, was ich will?

D
496 Beiträge seit 2005
vor 14 Jahren

private?

"Programming is similar to sex. If you make a mistake, you have to support it for the rest of your life."

M
6 Beiträge seit 2009
vor 14 Jahren

Hallo,

"private" geht nicht, da es Member echt NUR innerhalb der Klasse sichtbar macht.

@Kuehner:
So wie du es beschrieben hast, geht es mit den normalen C#-Zugriffsmodifizierern nicht.
Was willst du denn machen? Vielleicht ist das auch einfach nur der falsche Ansatz!?

Grüße

S
902 Beiträge seit 2007
vor 14 Jahren

private?

wird wohl nicht gehen

mfg
serial

K
Kuehner Themenstarter:in
489 Beiträge seit 2006
vor 14 Jahren

Nö... private geht noch weniger, klar.

Ich möchte einfach mit der "KlasseTante" objekt-Infos erstellen. Die Objekt-Infos haben eine gewisse Intelligenz (hier einfach nur Inkrementieren einer Nummer). Auf die Intelligenz-Funktionen der Objekt-Infos möchte ich allerdings nur innerhalb der KlasseTante zugreifen. Andere Klassen sollen diese Funktionen nicht mehr verwenden dürfen.

Gut, im Zweifelsfall mache ich die Funktionen einfach public...

S
902 Beiträge seit 2007
vor 14 Jahren

Dann mach einen Proxy um diese Klassen welche deine Hauptklasse zurückgibt, dieser Proxy verhindert die Intelligenzfunktionen.

http://www.dofactory.com/Patterns/PatternProxy.aspx

Edit: oder wohl unsauber: Mach ein Interface welches die erlaubten Methoden hat(welche auch von ausserhalb aufgerufen werden können) und gib nur das Interface zurück.
Intern castest du immer in den richtigen Klassentyp und kannst auf alle Member zugreifen (also auch auf die, welche nicht im Interface deklariert sind und somit von ausserhalb nicht aufrufbar).

mfg
serial

K
Kuehner Themenstarter:in
489 Beiträge seit 2006
vor 14 Jahren

Guter Tipp!

Was das etwa so gemeint?? Kommt mir grad ein bischen komisch vor.


public class KlassenTante
{
    public class KlassenOnkel
    {
        int test;

        protected void AddTest(int value)
        {
            test += value;
        }

        public int Test
        {
            get
            {
                return test;
            }
        }
    }

    public class OnkelProxy : KlassenOnkel
    {
        KlassenOnkel ko = new KlassenOnkel();

        public void AddTestFunction(int value)
        {
            base.AddTest(value);
        }

        public KlassenOnkel KO
        {
            get
            {
                return ko;
            }
        }
    }

    public KlassenOnkel GibOnkel()
    {
        OnkelProxy op = new OnkelProxy();
        op.AddTestFunction(1);
        op.AddTestFunction(2);
        op.AddTestFunction(3);
        return op.KO;
    }
} 


S
902 Beiträge seit 2007
vor 14 Jahren

nein, schau dir nochmal den link genau an den ich dir geschickt habe =)

mfg
serial

K
Kuehner Themenstarter:in
489 Beiträge seit 2006
vor 14 Jahren

Das Problem: Ich kann es gerade nicht auf mein eigenes Problem transferirern. Interfaces lassen wir jetzt mal draußen, das spielt ja keine Rolle.

Auf diese Art deckt es allerdings meine Bedürftnisse:


public class KlassenTante
{
    public class KlassenOnkel
    {
        protected int test;

        public int Test
        {
            get
            {
                return test;
            }
        }
    }

    private class OnkelProxy : KlassenOnkel
    {
        public void AddTest(int value)
        {
            test = test + value;
        }

        public KlassenOnkel KO
        {
            get
            {
                return this;
            }
        }
    }

    public KlassenOnkel GibOnkel()
    {
        OnkelProxy op = new OnkelProxy();
        op.AddTest(1);
        op.AddTest(2);
        op.AddTest(3);
        return op.KO;
    }
} 

Wurde editiert!

S
902 Beiträge seit 2007
vor 14 Jahren

Nein eher in die richtung:



abstract class KlassenOnkel
{
 public abstract void Add(int i);
 int Test{get;set;};
}

public class RichtigerOnkel:KlassenOnkel
{
 public void Add(int i)
 {
   //hier deine intelligenz
 }

 public int Test
{ get {return irgendwas;}
   set{irgendwas=value;}
}
}

public class OnkelProxy:KlassenOnkel
{
  private KlassenOnkel _onkel = new RichtigerOnkel();
  public void Add(int i)
 {
   throw new OperationException("Darfst du nicht");
 }

 public int Test
{ get {return _onkel.irgendwas;}
   set{_onkel.irgendwas = value;}
}
}

K
Kuehner Themenstarter:in
489 Beiträge seit 2006
vor 14 Jahren

Ok. Interessant. Aber dass man Test setten kann, will ich schon mal gar nicht. Aber das tut jetzt auch nichts zur Sache.

Mein Verständnisproblem: Wie würde in Deinem Fall die Funktion GibOnkel() denn aussehen? Etwa so?


    public KlassenOnkel GibOnkel()
    {
        RichtigerOnkel op = new RichtigerOnkel();
        op.AddTest(1);
        op.AddTest(2);
        op.AddTest(3);
        return ???;
    }

Der, der ausserhalb von KlasseTante auf das Objekt OnkelProxy zugreift, darf auf keinen Fall die Intelligenzfunktion benutzen dürfen. Das ist bei dir ja durch die Exception geregelt. Doch wie bekomme ich den Proxy aus dem Richtigen Onkel "raus"?

49.485 Beiträge seit 2005
vor 14 Jahren

Hallo

warum schließt ihr die ganze Zeit Interfaces aus? Das ist doch eine einfache, saubere Lösung.

public class KlassenTante
{
    public interface IKlassenOnkel // <== hier neues Interface
    {
       int Test { get; }
    }

    private class KlassenOnkel : IKlassenOnkel  // <== hier private verwendet und vom Interface "geerbt"
    {
        int test;

        public void AddTest(int value)
        {
            test += value;
        }

        public int Test
        {
            get
            {
                return test;
            }
        }
    }

    public IKlassenOnkel GibOnkel() // <== hier Rückgabetyp geändert
    {
        KlassenOnkel ko = new KlassenOnkel();
        ko.AddTest(1);
        ko.AddTest(2);
        ko.AddTest(3);
        return ko;
    }
}

Das Interface könnte man sogar außerhalb der Klasse definieren, dann spart man sich das umständliche KlassenTante.IKlassenOnkel.

herbivore

K
Kuehner Themenstarter:in
489 Beiträge seit 2006
vor 14 Jahren

Stimmt... das wäre die beste Lösung.

Mein Info-Objekt (also in diesem Fall KlasseOnkel) hat in meiner wahren Applikation jedoch viele Properties und ich mache es nicht aus Faulheit 😉

Aber ich werde es wahrscheinlich noch ändern...

49.485 Beiträge seit 2005
vor 14 Jahren

Hallo Kuehner,

ansonsten kannst du bei AddTest auch internal statt public verwenden.

herbivore

K
Kuehner Themenstarter:in
489 Beiträge seit 2006
vor 14 Jahren

Ok, Danke. Das war eigentlich das, was ich anfänglich gesucht hätte. Aber ich schreibe gerade meinen Code auf die Interface-Lösung um. Ist sauberer.

2.187 Beiträge seit 2005
vor 14 Jahren

Hallo Kuehner,

Mein Info-Objekt (also in diesem Fall KlasseOnkel) hat in meiner wahren Applikation jedoch viele Properties und ich mache es nicht aus Faulheit 😉

Die Ausrede zählt nicht. 😉 VisualStudio kann mit einem Rechts- und zwei Links-Clicks zu einer Klasse ein interface erstellen.
[EDIT]Ach ja, wäre sicher interesant: Rechts-Click auf die Klasse (die Deklaration). Im Kontextmenü auf "Umgestallten" und darunter auf "Schnittstelle extrahieren". Ab hier dem Dialog folgen.[/EDIT]

Gruß
Juy Juka

S
902 Beiträge seit 2007
vor 14 Jahren

@herbivore: ich habs ja nicht ausgeschlossen, war mir nur nicht sicher ob es wirklich eine "saubere" lösung ist.

Nun weiß ichs ja =)

mfg
serial