Autor Beitrag
Kasko
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 101

Win 10
C# C++ (VS 2017/19), (Java, PHP)
BeitragVerfasst: Fr 31.05.19 01:36 
Servus,

Die Nutzung des 'new' Keywords zur Erstellung/Initialisierung von Objekten ist ja glasklar, sinnvoll und nicht anzuzweifeln. Aber ich verstehe nicht warum die Funktion in C# eingebaut wurde, dass man mit dem 'new' Keyword einfach Properties, etc. einer Basisklasse überschreiben kann. Dadurch wird doch das Prinzip der objektorientierten Kapselung zerstört. Ein Beispiel:

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
public class Mensch {
  protected string _name;

  /// <summary>
  /// Ruft den Namen des Menschen ab. Man kann ihn natürlich nicht einfach so ändern. Geht im echten Leben ja auch nicht.
  /// </summary>
  public string Name { get => _name; }

  /// <summary>
  /// 'Erstellt' einen Menschen und legt bei 'der Geburt' den Namen fest.
  /// </summary>
  /// <param name="name">Der Name des Menschen.</param>
  public Mensch(string name) {
    _name = name;
  }
}


So wäre es logisch. Aber warum kann ich jetzt die Property 'Name' in einer erbenden Klasse neu definieren. Das zerstört ja das ganze Verhalten das vorher, vielleicht sogar von einem anderen Programmierer, festgelegt wurde. Dann würde das Kind ja seinem Parent widersprechen!!!

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
public class UmbenennbarerMensch : Mensch {
  /// <summary>
  /// Ruft den Namen des Menschen ab oder legt diesen fest. Aus irgendeinem Grund soll man jetzt den Namen ändern können, obwohl es eigentlich anders vereinbart wurde.
  /// <see cref="Mensch"/>
  /// Sinn dahinter ist anzuzweifeln.
  /// </summary>
  public new string Name { get => _name; set => _name = value; }

  /// <summary>
  /// 'Erstellt' einen Menschen und legt bei 'der Geburt' den Namen fest.
  /// </summary>
  /// <param name="name">Der Name des Menschen.</param>
  public UmbenennbarerMensch(string name) : base(name){ }
}


Kann mir das bitte jemand erklären, warum man sowas machen darf?
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4259
Erhaltene Danke: 911

Win10
C#, C++ (VS 2015/17)
BeitragVerfasst: Fr 31.05.19 09:21 
Damit wird den C#-Programmierern alle Möglichkeiten geboten.
Für virtual-Methoden gibt es override und für nicht-virtuelle (welche ja Standard sind, im Gegensatz zu z.B. Java) gibt es eben new. In Polymorphism, Method Hiding and Overriding in C# wird das auch detailliert dargestellt.

Und ohne den new-Modifizierer kommt ja eine entsprechende Warnung "The keyword new is required on 'MyDerivedC.X' because it hides inherited member 'MyBaseC.X'.

Und manchmal benötigt man eben Ausnahmen, z.B. wenn man beim Heiraten den Nachnamen des Partners annimmt (um bei deinem Beispiel zu bleiben).
OlafSt
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 471
Erhaltene Danke: 94

Win7, Win81, Win10
Tokyo, VS2017
BeitragVerfasst: Fr 31.05.19 10:08 
Bieten nicht alle objektorientierten Sprachen so eine Möglichkeit ? In Delphi gibt es dafür z.B. das Keyword reintroduce.

_________________
Lies, was da steht. Denk dann drüber nach. Dann erst fragen.
Palladin007
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1207
Erhaltene Danke: 159

Windows 10 x64 Home Premium
C# (VS 2015 Enterprise)
BeitragVerfasst: Fr 31.05.19 10:35 
Zitat:
Dadurch wird doch das Prinzip der objektorientierten Kapselung zerstört

Finde ich, trifft's ganz gut :D

Ich behaupte auch, es gibt fast keinen sinnvollen Anwendungsfall, aber es ist trotzdem dabei, damit man die Möglichkeit hat, falls man sie doch Mal braucht.

Ich persönlich nutze das eigentlich nur in z.B. so einem Fall:

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:
public class Entry
{
    public object Value { get; }

    public Entry(object value)
    {
        Value = value;
    }
}

public class Entry<TValue> : Entry
{
    public new TValue Value
    {
        get => (TValue)base.Value;
    }

    public Entry(TValue value)
       : base(value)
    {
    }
}


Damit verändere ich das Grundverhalten nicht, ich den selben Wert an, nur mit einem Cast.
Ob das jetzt so gut ist, kann man drüber streiten und im Zweifelsfall ist mir auch das Interface mit explizit implementierter Value-Property lieber.


Zuletzt bearbeitet von Palladin007 am Fr 31.05.19 19:14, insgesamt 1-mal bearbeitet
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4259
Erhaltene Danke: 911

Win10
C#, C++ (VS 2015/17)
BeitragVerfasst: Fr 31.05.19 10:59 
@Palladin007: Du meinst sicherlich
ausblenden C#-Quelltext
1:
public class Entry<TValue> : Entry					
?
Palladin007
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1207
Erhaltene Danke: 159

Windows 10 x64 Home Premium
C# (VS 2015 Enterprise)
BeitragVerfasst: Fr 31.05.19 19:15 
Ja genau, das meine ich.
Danke für die Korrektur, hab's oben angepasst.