Autor Beitrag
nerdfactor
Hält's aus hier
Beiträge: 5



BeitragVerfasst: Do 14.10.10 13:21 
Hallo,
ich habe zur zeit ein problem bei einem kleinen projekt mit vererbung und dem zugriff auf variablen innerhalb der objekte. hier mal ein kurzes beispiel:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
static void Main(String[] args) {
  ChildClass cc = new ChildClass();
}

class BaseClass {

  public String str = "BaseClass";

  public BaseClass() {
    this.doSomething();
  }

  public void doSomething() {
    Console.WriteLine(this.str);
  }
}

class ChildClass : BaseClass{

  new public String str = "ChildClass";

  public ChildClass() : base(){
      
  }

  public void doSomethingElse() {
    //does something else that has nothing todo with doSomething
  }
}


wenn ich das ausführe, wird in der konsole "BaseClass" ausgegeben. ich hätte allerdings erwartet, das "ChildClass" ausgegeben wird, da doSomething von ChildClass aufgerufen wird und str dort den wert "ChildClass" hat.

habe ich da einfach nur ein denkfehler, oder etwas in der richtung? und wie kann ich das erreichen, was ich eigentlich erwartet habe?

ich hoffe jemand kann mir helfen.
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4796
Erhaltene Danke: 1059

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Do 14.10.10 13:33 
Kennst du schon das Schlüsselwort 'virtual'?

Du hast in ChildClass die Variable mittels 'new' überschrieben (das man nur in sehr wenigen Situationen einsetzen sollte), jedoch kennt BaseClass nur die eigene Variable 'str' und gibt daher dessen Inhalt "BaseClass" aus.

Richtig wäre es also so:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
static void Main(String[] args) {
  ChildClass cc = new ChildClass();
}

class BaseClass
{
  public virtual String str = "BaseClass";

  public BaseClass() {
    this.doSomething();
  }

  public void doSomething() {
    Console.WriteLine(this.str);
  }
}

class ChildClass : BaseClass
{
  public override String str = "ChildClass";

  public ChildClass() : base(){
      
  }
}

Beachte also die beiden Schlüsselwörter 'virtual' und 'override' (zum Überschreiben).

Ich nehme mal an, daß du noch Anfänger bist und daher dies eines deiner ersten Übungsprogramme ist? Besser ist es nämlich, wenn du Eigenschaften (Properties) bzw. die Methoden als 'virtual' deklarierst. Klassenmember (Felder) sollten außerdem immer 'private' sein.
DuxGladii
Hält's aus hier
Beiträge: 8

Win7
VS2010, C#
BeitragVerfasst: Do 14.10.10 13:36 
Hallo nerdfactor,

da du doSomething nicht überschreibst, wird die Funktion der Basis-Klasse aufgerufen, die den String der Basis-Klasse zurückgibt. Willst du den String der ChildClass zurückgeben, kannst du die Funktion in der ChildClass überschreiben mit

ausblenden C#-Quelltext
1:
2:
3:
4:
public override void doSomething()
{
return this.str; // wenn du hier base.str schreibst, solltest du BaseClass zurückgeliefert bekommen
}
nerdfactor Threadstarter
Hält's aus hier
Beiträge: 5



BeitragVerfasst: Do 14.10.10 13:46 
ja c# ist neu für mich. ich steige um von webentwicklung mit php, ruby und javascript. anscheinend habe ich daher tatsächlich denkfehler wenn es um das static binding geht.

wenn ich die variablen um virtual bzw. override ergänze, lässt sich das programm nicht kompilieren mit dem hinweis "The modifier 'virtual' is not valid for this item" bzw. "The modifier 'override' is not valid for this item".
doSomething in ChildClass zu überschreiben würde doch den ganzen sinn aus der verwerbung nehmen. immerhin möchte ich ja das ChildClass die funktionalität von BaseClass erbt damit ich sie nicht mehrfach schreiben muss.

es bleibt daher noch die frage wie ich das erreiche was ich eigentlich haben möchte.
DuxGladii
Hält's aus hier
Beiträge: 8

Win7
VS2010, C#
BeitragVerfasst: Do 14.10.10 13:53 
ChildClass erbt ja auch die Funktionalität von BaseClass, aber du willst ja die Funktion verändern, weil du nicht die Variable von BaseClass sondern von ChildClass zurückgeben willst, deshalb musst du sie überschreiben (virtual hab ich in meinem vorigen Post vergessen zu erwähnen).
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4796
Erhaltene Danke: 1059

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Do 14.10.10 14:15 
Sorry, 'virtual' funktioniert ja gar nicht bei Klassenmembern (daher auch mein Hinweis bzgl. Eigenschaften und Methoden -).

Du könntest also dann folgendes verwenden (in Anlehnung an den Code von DuxGladii):
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
static void Main(String[] args) {
  ChildClass cc = new ChildClass();
}

class BaseClass
{
  private String str = "BaseClass";

  public BaseClass() {
    this.doSomething();
  }

  public virtual void doSomething() {
    Console.WriteLine(this.str);
  }
}

class ChildClass : BaseClass
{
  private new String str = "ChildClass";

  public ChildClass() : base(){
      
  }

  public override void doSomething() {
    Console.WriteLine(this.str);
  }
}

Jede Klasse hat nun also eine private Variable (hier dann doch mittels 'new' überschrieben) und implementiert dann jeweils 'doSomething'.

Besser aber nun die Variante mit Eigenschaften:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
static void Main(String[] args) {
  ChildClass cc = new ChildClass();
}

class BaseClass
{
  public virtual String Str { get { return "BaseClass"; } }

  public BaseClass() {
    this.doSomething();
  }

  public void doSomething() {
    Console.WriteLine(this.Str);
  }
}

class ChildClass : BaseClass
{
  public override String Str { get { return "ChildClass"; } }

  public ChildClass() : base(){
      
  }
}
nerdfactor Threadstarter
Hält's aus hier
Beiträge: 5



BeitragVerfasst: Do 14.10.10 14:20 
ok das scheint zu funktionieren. vielen dank.
da werde ich mir wohl das mit dem Properties genauer angucken müssen.
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4708
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Do 14.10.10 14:32 
Da das mit virtual/override geklärt ist nur folgendes kurz zu deinem geschilderten Anwendungsfall. Wenn das nicht nur ein Beispiel ist sondern dein wirklicher Anwendungsfall dann kommst du an den Klassennamen einfach über das Type Objekt deiner Klasse.

Also anstatt eine Literal zurück zu liefern einfach in BaseClass folgendes machen.
ausblenden C#-Quelltext
1:
  public String Str { get { return this.GetType().Name; } }					

Wenn du denn Namen nur veröffentlichst um darüber zu prüfen was du für einen Typ den gerade an der Hand hast so solltest du auch eher den is Operator verwenden.