Discussion:
anfängerfragen: Überladener Konstruktor vererben
(zu alt für eine Antwort)
Peter Ramsebner
2005-01-02 15:52:27 UTC
Permalink
Hallo miteinander,

können Überladene Konstruktoren nicht vererbt werden?

Beispiel:

class Person
sub new()
....
end sub

sub new(vorname as string, nachname as string)
...
end sub

dann weiter:
class Angestellter
inherits Person


dann wird ein Angestellter instanziert:
dim a as new angestellter("peter", "ramsebner")

das geht dann nicht: "Zu viele Argumente für New()"
In der Doku habe ich nichts gefunden....

Danke für eure Hilfe
Peter
Herfried K. Wagner [MVP]
2005-01-02 15:56:39 UTC
Permalink
Hallo Peter!
Post by Peter Ramsebner
können Überladene Konstruktoren nicht vererbt werden?
Nein. Konstruktoren werden nicht vererbt, sondern müssen in der abgeleiteten
Klasse neu implementiert werden. Üblicherweise erfolgt dies mit einem Aufruf
des Konstruktors der Basisklasse, wenn Konstruktoren gleicher Signatur
benötigt werden:

\\\
Public Class Base
Public Sub New(ByVal i As Integer, ByVal s As String)
...
End Sub
End Class

Public Class Derived
Inherits Base

Public Sub New(ByVal i As Integer, ByVal s As String)
MyBase.New(i, s)
End Sub
End Class
///

Dass Konstruktoren nicht vererbt werden, ist keine sinnfreie Einschränkung
von .NET, sondern hat seine Ursache darin, dass eine abgeleitete Klasse
eventuell zusätzliche Daten zur Initialisierung benötigt, also bestehende
Konstruktoren für die Instanzierung/Initialisierung nicht ausreichend sein
können.
--
M S Herfried K. Wagner
M V P <URL:http://dotnet.mvps.org/>
V B <URL:http://dotnet.mvps.org/dotnet/faqs/>
Harald M. Genauck
2005-01-02 16:26:40 UTC
Permalink
Hallo Herfried,
Post by Herfried K. Wagner [MVP]
Dass Konstruktoren nicht vererbt werden, ist keine sinnfreie
Einschränkung von .NET, sondern hat seine Ursache darin, dass eine
abgeleitete Klasse eventuell zusätzliche Daten zur Initialisierung
benötigt, also bestehende Konstruktoren für die
Instanzierung/Initialisierung nicht ausreichend sein können.
Das will mir als Grund aber nicht ganz einleuchten, zumindest nicht als
zwingender Grund. Denn wenn Konstruktoren vererbbar wären, könnten sie
ebenso sowohl überschreibbar als auch überladbar sein - und damit durchaus
die Möglichkeit für zusätzliche Initialisierungen und Parameter für die
Ableitung(en) anbieten...


Viele Grüße

Harald M. Genauck

ABOUT Visual Basic - das Webmagazin
http://www.aboutvb.de
Herfried K. Wagner [MVP]
2005-01-02 16:38:55 UTC
Permalink
Hallo Harald!
Post by Harald M. Genauck
Post by Herfried K. Wagner [MVP]
Dass Konstruktoren nicht vererbt werden, ist keine sinnfreie
Einschränkung von .NET, sondern hat seine Ursache darin, dass eine
abgeleitete Klasse eventuell zusätzliche Daten zur Initialisierung
benötigt, also bestehende Konstruktoren für die
Instanzierung/Initialisierung nicht ausreichend sein können.
Das will mir als Grund aber nicht ganz einleuchten, zumindest nicht als
zwingender Grund. Denn wenn Konstruktoren vererbbar wären, könnten sie
ebenso sowohl überschreibbar als auch überladbar sein - und damit durchaus
die Möglichkeit für zusätzliche Initialisierungen und Parameter für die
Ableitung(en) anbieten...
Nehmen wir an, in einer Basisklasse ist ein Konstruktor 'New(A, B)'
definiert. Wenn die abgeleitete Klasse allerdings zur Initialisierung
/zwingend/ noch einen Wert 'C' benötigt, ist der Konstruktor 'New(A, B)'
unbrauchbar -- und wird aus dem Grund auch nicht geerbt. Selbst die
Möglichkeit, den Konstruktor zu überschreiben, hilft da wenig, denn der Wert
'C' kann dadurch ja nicht durch den Benutzer der Klasse übergeben werden.
Allenfalls könnte man eine Ausnahme werfen, aber da verzichtet man besser
überhaupt auf den Konstruktor, wo doch überdies Polymorphie über den
Konstruktor dahingehend nicht möglich ist, dass ein Konstruktur immer genau
ein Objekt eines bereits zur Kompilierungszeit eindeutig bekannten Typs
zurückgibt. Überladen kann man Konstruktoren ja sowieso.
--
M S Herfried K. Wagner
M V P <URL:http://dotnet.mvps.org/>
V B <URL:http://dotnet.mvps.org/dotnet/faqs/>
Harald M. Genauck
2005-01-02 18:35:52 UTC
Permalink
Hallo Herfried,
Post by Herfried K. Wagner [MVP]
Post by Harald M. Genauck
Post by Herfried K. Wagner [MVP]
Dass Konstruktoren nicht vererbt werden, ist keine sinnfreie
Einschränkung von .NET, sondern hat seine Ursache darin, dass eine
abgeleitete Klasse eventuell zusätzliche Daten zur Initialisierung
benötigt, also bestehende Konstruktoren für die
Instanzierung/Initialisierung nicht ausreichend sein können.
Das will mir als Grund aber nicht ganz einleuchten, zumindest nicht als
zwingender Grund. Denn wenn Konstruktoren vererbbar wären, könnten sie
ebenso sowohl überschreibbar als auch überladbar sein - und damit
durchaus die Möglichkeit für zusätzliche Initialisierungen und Parameter
für die Ableitung(en) anbieten...
Nehmen wir an, in einer Basisklasse ist ein Konstruktor 'New(A, B)'
definiert. Wenn die abgeleitete Klasse allerdings zur Initialisierung
/zwingend/ noch einen Wert 'C' benötigt, ist der Konstruktor 'New(A, B)'
unbrauchbar -- und wird aus dem Grund auch nicht geerbt. Selbst die
Möglichkeit, den Konstruktor zu überschreiben, hilft da wenig, denn der
Wert 'C' kann dadurch ja nicht durch den Benutzer der Klasse übergeben
werden.
Ich sehe immer noch keinen Unterschied zu "normalen" Methoden, bei denen
das gleiche Problem-Szenario ebenso auftreten kann.
Post by Herfried K. Wagner [MVP]
Allenfalls könnte man eine Ausnahme werfen,
...was man bei "normalen" Methoden ja genau dann tun muss, weil sie eben
vererbt werden.

Oder gibt es eine Möglichkeit, einer Ableitung eine geerbte Methode
"wegzunehmen", d.h. sie auszublenden und gegen Verwendung zu sperren? Ich
behelfe mir bisher immer damit, in der Ableitung eine nicht verwendbare
Basis-Methode als "Private Overrides..." zu deklarieren. Das erscheint mir
zwar wenig elegant, funktioniert aber offensichtlich soweit, so lange die
Ableitung nicht auf den Basis-Typ gecastet wird...


Viele Grüße

Harald M. Genauck

ABOUT Visual Basic - das Webmagazin
http://www.aboutvb.de
Herfried K. Wagner [MVP]
2005-01-02 20:13:04 UTC
Permalink
Hallo Harald!
Post by Harald M. Genauck
Post by Herfried K. Wagner [MVP]
Post by Harald M. Genauck
Post by Herfried K. Wagner [MVP]
Dass Konstruktoren nicht vererbt werden, ist keine sinnfreie
Einschränkung von .NET, sondern hat seine Ursache darin, dass eine
abgeleitete Klasse eventuell zusätzliche Daten zur Initialisierung
benötigt, also bestehende Konstruktoren für die
Instanzierung/Initialisierung nicht ausreichend sein können.
Das will mir als Grund aber nicht ganz einleuchten, zumindest nicht als
zwingender Grund. Denn wenn Konstruktoren vererbbar wären, könnten sie
ebenso sowohl überschreibbar als auch überladbar sein - und damit
durchaus die Möglichkeit für zusätzliche Initialisierungen und Parameter
für die Ableitung(en) anbieten...
Nehmen wir an, in einer Basisklasse ist ein Konstruktor 'New(A, B)'
definiert. Wenn die abgeleitete Klasse allerdings zur Initialisierung
/zwingend/ noch einen Wert 'C' benötigt, ist der Konstruktor 'New(A, B)'
unbrauchbar -- und wird aus dem Grund auch nicht geerbt. Selbst die
Möglichkeit, den Konstruktor zu überschreiben, hilft da wenig, denn der
Wert 'C' kann dadurch ja nicht durch den Benutzer der Klasse übergeben
werden.
Ich sehe immer noch keinen Unterschied zu "normalen" Methoden, bei denen
das gleiche Problem-Szenario ebenso auftreten kann.
Das Problem kann bei normalen Methoden in dieser Form nicht auftreten, da
die normalen Methoden ja in einer der Basisklassen implementiert sind und
aus dem Grund für sich funktionieren bzw. ihre Funktion bei der Basisklasse
spezifiziert ist und sich durch Vererbung (im Normalfall, sofern nicht
überschrieben/überschattet wird) nicht ändert. Überschriebene bzw.
überschattete Mitglieder sind dann aber klar als solche erkennbar, etwa im
Objektbrowser.

Jedes Objekt des Typs 'B' kann auch als Objekt des Typs 'A' gesehen werden,
wenn der Typ 'B' vom Typ 'A' erbt. Das impliziert, dass jedes Objekt des
Typs 'B' auch das kann, was ein Objekt vom Typ 'A' kann. Durch Überschreiben
kann es nicht zu ungewünschten Zuständen im Status eines Objekts gelangen,
da Überschreiben immer nur über eine Vererbungsebene möglich ist (d.h. ein
Überschreiben von 'MyBase.MyBase.Bla' ist nicht möglich).

Würden Konstruktoren geerbt werden, wäre jedoch genau dies möglich, d.h. es
kann zu inkonsistenten Objektzuständen kommen. Betrachten wir dazu folgendes
Beispiel:

\\\

' Das sollte die 'Object'-Klasse des Frameworks darstellen und ist hier
' nur zu Zwecken der besseren Verständlichkeit angeführt.
Public Class Object
Public Sub New()
...
End Sub
End Class

Public Class FileInfo
Inherits Object

Private m_FileName As String

Public Sub New(ByVal FileName As String)
m_FileName = FileName
End Sub

Public ReadOnly Property FileName() As String
Get
Return m_FileName
End Get
End Class

Public Class SpecialFieldInfo
Inherits FieldInfo

Public Sub New()
MyBase.New("C:\AUTOEXEC.BAT")
End Sub

Public Sub New(ByVal FileName As String)
MyBase.New(FileName)
End Sub
End Class
///

Obenstehender Code definiert die Klasse 'FileInfo', die von 'Object' erbt,
sowie eine Klasse 'SpecialFileInfo', die 'FileInfo' erweitert.

Nehmen wir nun an, Konstruktoren könnten vererbt werden. Dann würde
'FileInfo', wie 'Object', über einen parameterlosen Konstruktor verfügen.
Nehmen wir weiters an, dass die Dokumentation zur Eigenschaft 'FileName' der
Klasse 'FileInfo' besagt, dass der bei der Erstellung der Klasse angegebene
Dateiname zurückgegeben wird und ausserdem die weitere interne Logik der
Klasse 'FileInfo' nur dann funktioniert, wenn bereits im Konstruktor der
Klasse 'm_FileName' auf einen Pfad gesetzt wurde. Instanziert nun der
Benutzer der Klasse 'FileInfo' mit dem von 'Object' geerbten, parameterlosen
Konstruktor, kann das zuvor Gesagte nicht mehr sichergestellt werden.

'SpecialFileInfo' besitzt zwei Konstruktoren, einen parameterlosen und einen
parametrisierten. Da in 'FileInfo' kein parameterloser Konstruktor vorhanden
ist (und damit festgelegt wird, dass jede Ableitung der Klasse einen
Dateinamen übergeben muss, um die Funktionalität der Klasse
sicherzustellen), müssen alle in 'SpecialFileInfo' vorhandenen Konstruktoren
den Konstruktor der Basisklasse aufrufen. Dadurch wird garantiert, dass
diese auch problemlos initialisiert werden kann. Würde, weil Konstruktoren
geerbt werden, weiterhin der parameterlose Konstruktor aus 'Object' auch in
'SpecialFileInfo' vorhanden sein, könnte nicht garantiert werden, dass sich
Objekte des Typs 'FileInfo' (und davon abgeleiteten Typen) immer in einem
konsistenten Zustand befinden.
Post by Harald M. Genauck
Post by Herfried K. Wagner [MVP]
Allenfalls könnte man eine Ausnahme werfen,
...was man bei "normalen" Methoden ja genau dann tun muss, weil sie eben
vererbt werden.
Tut man aber im Normalfall nicht, zumindest sind mir noch keine solchen
Fälle begegnet -- und selbst wenn, würde ich dies in den meisten Fällen als
Indikator für ein unsauberes Klassendesign werten.
Post by Harald M. Genauck
Oder gibt es eine Möglichkeit, einer Ableitung eine geerbte Methode
"wegzunehmen", d.h. sie auszublenden und gegen Verwendung zu sperren? Ich
behelfe mir bisher immer damit, in der Ableitung eine nicht verwendbare
Basis-Methode als "Private Overrides..." zu deklarieren. Das erscheint mir
zwar wenig elegant, funktioniert aber offensichtlich soweit, so lange die
Ableitung nicht auf den Basis-Typ gecastet wird...
Etwas wegzunehmen, was bereits da ist, widerspricht Vererbung als Mittel zur
Erweiterung. Was die Basisklasse kann, kann auch die abgeleitete Klasse.
Deshalb gibt es auch keine direkten Mittel, die das Entfernen von Geerbtem
zur "Standardvorgehensweise" machen. Allenfalls ist in Frage zu stellen, ob
die Ableitung überhaupt sinnvoll ist, wenn Funktionalität der Basisklasse
nicht weiter bereitgestellt werden soll.
--
M S Herfried K. Wagner
M V P <URL:http://dotnet.mvps.org/>
V B <URL:http://dotnet.mvps.org/dotnet/faqs/>
Herfried K. Wagner [MVP]
2005-01-02 20:50:45 UTC
Permalink
Errata:

Alle Vorkommen von "Field" sind durch "File" zu ersetzen (der Fehler hat
sich einige Male eingeschlichen).
--
M S Herfried K. Wagner
M V P <URL:http://dotnet.mvps.org/>
V B <URL:http://dotnet.mvps.org/dotnet/faqs/>
Harald M. Genauck
2005-01-02 20:51:43 UTC
Permalink
Hallo Herfried,
Post by Herfried K. Wagner [MVP]
Post by Harald M. Genauck
Oder gibt es eine Möglichkeit, einer Ableitung eine geerbte Methode
"wegzunehmen", d.h. sie auszublenden und gegen Verwendung zu sperren?
Ich behelfe mir bisher immer damit, in der Ableitung eine nicht
verwendbare Basis-Methode als "Private Overrides..." zu deklarieren. Das
erscheint mir zwar wenig elegant, funktioniert aber offensichtlich
soweit, so lange die Ableitung nicht auf den Basis-Typ gecastet wird...
Etwas wegzunehmen, was bereits da ist, widerspricht Vererbung als Mittel
zur Erweiterung. Was die Basisklasse kann, kann auch die abgeleitete
Klasse. Deshalb gibt es auch keine direkten Mittel, die das Entfernen von
Geerbtem zur "Standardvorgehensweise" machen.
Grundsätzlich hast Du sicher Recht.

Das Problem, weswegen ich verbergen können will, stellt sich etwa bei
Eigenschaften. Etwa wenn eine Basis-Klasse lediglich eine bestimmte
Eigenschaft als ReadOnly bieten soll, eine Ableitung davon aber ReadWrite.
Zunächst immer noch kein Problem, da sich die Eigenschaft ja überschatten
lässt. Zum Problem wird's dann, wenn aus Polymorphie-Aspekten
Schnittstellen ins Spiel kommen. Wenn etwa die Basis-Klasse eine
Schnittstelle implementiert, in der jene Eigenschaft eben als ReadOnly
deklariert ist, und die Ableitung eine Schnittstelle implementieren soll,
in der die Eigenschaft als ReadWrite deklariert ist. Die Ableitung bietet
dann beide Eigenschaften (wobei diese sich ja ein wenig im Namen
unterscheiden müssen). Verwendet werden soll aber ausschließlich die
Eigenschaft, die in der Ableitung von der zweiten Schnittstelle
implementiert wird.
Post by Herfried K. Wagner [MVP]
Allenfalls ist in Frage zu stellen, ob die Ableitung überhaupt sinnvoll
ist, wenn Funktionalität der Basisklasse nicht weiter bereitgestellt
werden soll.
Doch, eine Ableitung halte ich sicher nach wie vor sinnvoll, wenn ein
annehmbar sinnvoller Gutteil der Basis-Funktionalität trotz Verbergens
einzelner Member weiterhin genutzt werden soll und vor allem die
Polymorphie weiterhin benötigt wird.


Viele Grüße

Harald M. Genauck

ABOUT Visual Basic - das Webmagazin
http://www.aboutvb.de
Peter Fleischer
2005-01-02 21:05:35 UTC
Permalink
Herfried K. Wagner [MVP] wrote:
...
einen Pfad gesetzt wurde. Instanziert nun der Benutzer der Klasse
'FileInfo' mit dem von 'Object' geerbten, parameterlosen Konstruktor,
kann das zuvor Gesagte nicht mehr sichergestellt werden.
Herfried,
genau das Problem kann dir bei jeder Methode passieren, weshalb Shadows
anzuwenden ist.

Peter
Herfried K. Wagner [MVP]
2005-01-02 21:33:47 UTC
Permalink
Hallo Peter!
Post by Peter Fleischer
einen Pfad gesetzt wurde. Instanziert nun der Benutzer der Klasse
'FileInfo' mit dem von 'Object' geerbten, parameterlosen Konstruktor,
kann das zuvor Gesagte nicht mehr sichergestellt werden.
genau das Problem kann dir bei jeder Methode passieren, weshalb Shadows
anzuwenden ist.
Beispiel?
--
M S Herfried K. Wagner
M V P <URL:http://dotnet.mvps.org/>
V B <URL:http://dotnet.mvps.org/dotnet/faqs/>
Herfried K. Wagner [MVP]
2005-01-03 01:14:20 UTC
Permalink
Post by Herfried K. Wagner [MVP]
Post by Peter Fleischer
einen Pfad gesetzt wurde. Instanziert nun der Benutzer der Klasse
'FileInfo' mit dem von 'Object' geerbten, parameterlosen Konstruktor,
kann das zuvor Gesagte nicht mehr sichergestellt werden.
genau das Problem kann dir bei jeder Methode passieren, weshalb Shadows
anzuwenden ist.
Beispiel?
D.h. ich meine, dass ich nicht ganz verstehe, warum du in diesem
Zusammenhang 'Shadows' erwähnst.

'Shadows' dient m.W. dazu, weiterhin ein Mitglied einer Klasse (über die man
Kontrolle hat) benutzen zu lassen, selbst wenn in der Basisklasse der Klasse
(über die man evtl. keine Kontrolle hat) nachträglich ein "namensgleiches"
Mitglied eingefügt wird (etwa durch deren Hersteller). 'Shadows' ist
demzufolge ein Schlüsselwort, das erst im Laufe der Lebenszeit bzw.
Evolution einer Klasse hinzugefügt wird, um die ordnungsgemässe Funktion des
Codes sicherzustellen, wenn eine zuvor beschriebene Änderung in der
Basisklasse durchgeführt wurde.
--
M S Herfried K. Wagner
M V P <URL:http://dotnet.mvps.org/>
V B <URL:http://dotnet.mvps.org/dotnet/faqs/>
Harald M. Genauck
2005-01-03 08:50:58 UTC
Permalink
Hallo Herfried,
Post by Herfried K. Wagner [MVP]
Post by Herfried K. Wagner [MVP]
Post by Peter Fleischer
einen Pfad gesetzt wurde. Instanziert nun der Benutzer der Klasse
'FileInfo' mit dem von 'Object' geerbten, parameterlosen Konstruktor,
kann das zuvor Gesagte nicht mehr sichergestellt werden.
genau das Problem kann dir bei jeder Methode passieren, weshalb Shadows
anzuwenden ist.
Beispiel?
D.h. ich meine, dass ich nicht ganz verstehe, warum du in diesem
Zusammenhang 'Shadows' erwähnst.
'Shadows' dient m.W. dazu, weiterhin ein Mitglied einer Klasse (über die
man Kontrolle hat) benutzen zu lassen, selbst wenn in der Basisklasse der
Klasse (über die man evtl. keine Kontrolle hat) nachträglich ein
"namensgleiches" Mitglied eingefügt wird (etwa durch deren Hersteller).
'Shadows' ist demzufolge ein Schlüsselwort, das erst im Laufe der
Lebenszeit bzw. Evolution einer Klasse hinzugefügt wird, um die
ordnungsgemässe Funktion des Codes sicherzustellen, wenn eine zuvor
beschriebene Änderung in der Basisklasse durchgeführt wurde.
Ziemlich absurdes Argument, oder?

a) Denn ich hätte bestimmt keine Lust, in meinen u.U. zig Dutzenden von
Ableitungen einer von irgendeinem Hersteller gelieferten Basis-Klasse nach
einer Änderung eines Members durch eben diesen Hersteller zum einen überall
ein Shadows reinzufummeln und zum anderen auch noch um die ggfs.
vorhandenen MyBase-Aufrufe (die ja nun auch an die geänderte Signatur der
Basis-Klasse angepasst müssten) around-zu-worken... Und wer weiß, ob die
Basis-Klasse dann überhaupt noch so funktioniert wie zuvor...?

b) Ein Hersteller hat tunlichst die Finger von seinen einmal publizierten
Basis-Klassen und Schnittstellen zu lassen (Vertrag ist schließlich
Vertrag)!

Abgesehen davon: Den Sinn von Shadows sehe ich z.B. darin (vor allem, so
lange generische Klassen noch nicht verfügbar sind), Member mit
Rückgabewerten typsicher zu überschreiben. Oder eben, wie schon
beschrieben, Eigenschaften mit unterschiedlichen Zugriffsweisen zu
überschreiben.


Viele Grüße

Harald M. Genauck

ABOUT Visual Basic - das Webmagazin
http://www.aboutvb.de
Herfried K. Wagner [MVP]
2005-01-03 13:19:14 UTC
Permalink
Hallo Harald!
Post by Harald M. Genauck
Post by Herfried K. Wagner [MVP]
'Shadows' dient m.W. dazu, weiterhin ein Mitglied einer Klasse (über die
man Kontrolle hat) benutzen zu lassen, selbst wenn in der Basisklasse der
Klasse (über die man evtl. keine Kontrolle hat) nachträglich ein
"namensgleiches" Mitglied eingefügt wird (etwa durch deren Hersteller).
'Shadows' ist demzufolge ein Schlüsselwort, das erst im Laufe der
Lebenszeit bzw. Evolution einer Klasse hinzugefügt wird, um die
ordnungsgemässe Funktion des Codes sicherzustellen, wenn eine zuvor
beschriebene Änderung in der Basisklasse durchgeführt wurde.
Ziemlich absurdes Argument, oder?
Nein, sondern der Grund dafür, warum es 'Shadows' gibt. Beachte, dass
'Shadows' Polymorphie bricht und deshalb im Zuge eines "neuen
Klassendesigns" nicht verwendet werden sollte.

Siehe dazu auch (das trifft in etwa dein Beispiel mit den Eigenschaft und
der Schnittstelle):

<URL:http://groups.google.de/groups?selm=e2SML%23%23QEHA.3012%40tk2msftngp13.phx.gbl>
Post by Harald M. Genauck
a) Denn ich hätte bestimmt keine Lust, in meinen u.U. zig Dutzenden von
Ableitungen einer von irgendeinem Hersteller gelieferten Basis-Klasse nach
einer Änderung eines Members durch eben diesen Hersteller zum einen
überall ein Shadows reinzufummeln und zum anderen auch noch um die ggfs.
vorhandenen MyBase-Aufrufe (die ja nun auch an die geänderte Signatur der
Basis-Klasse angepasst müssten) around-zu-worken... Und wer weiß, ob die
Basis-Klasse dann überhaupt noch so funktioniert wie zuvor...?
b) Ein Hersteller hat tunlichst die Finger von seinen einmal publizierten
Basis-Klassen und Schnittstellen zu lassen (Vertrag ist schließlich
Vertrag)!
'Shadows' kommt erst dann ins Spiel, wenn der Hersteller der Klasse diese
/erweitert/, d.h. Mitglieder hinzufügt, die zufälligerweise bereits in
deinen Ableitungen vorhanden sind. In diesem Fall ist deine abgeleitete
Klasse nicht mehr kompilierbar und VB schlägt vor, das Mitglied in deiner
Klasse mit 'Shadows' zu markieren. Alternativ dazu kannst du natürlich auch
die Änderung (genauer: Erweiterung) in der Basisklasse zum Anlass nehmen,
deine Klasse weiterzuentwickeln, beispielsweise, wenn die Änderung in der
Basisklasse genau das hinzufügt, was du in der Ableitung selbst
implementiert hast.
Post by Harald M. Genauck
Abgesehen davon: Den Sinn von Shadows sehe ich z.B. darin (vor allem, so
lange generische Klassen noch nicht verfügbar sind), Member mit
Rückgabewerten typsicher zu überschreiben. Oder eben, wie schon
beschrieben, Eigenschaften mit unterschiedlichen Zugriffsweisen zu
überschreiben.
... mit dem Nachteil, dass Polymorphie dadurch ausgehebelt wird.
--
M S Herfried K. Wagner
M V P <URL:http://dotnet.mvps.org/>
V B <URL:http://dotnet.mvps.org/dotnet/faqs/>
Peter Fleischer
2005-01-03 07:31:24 UTC
Permalink
Herfried K. Wagner [MVP] wrote:
...
Post by Herfried K. Wagner [MVP]
Beispiel?
Hier dein Beispiel mit deinen Kommentaren:

Public Class Baseclass
Public Sub New()
' ...
End Sub
End Class

Public Class FileInfo
Inherits Baseclass

Private m_FileName As String

Public Shadows Sub New(ByVal FileName As String)
m_FileName = FileName
End Sub

Public ReadOnly Property FileName() As String
Get
Return m_FileName
End Get
End Property
End Class

Public Class SpecialFileInfo
Inherits FileInfo

Public Shadows Sub New()
MyBase.x("C:\AUTOEXEC.BAT")
End Sub

Public Shadows Sub New(ByVal FileName As String)
MyBase.x(FileName)
End Sub
End Class
Post by Herfried K. Wagner [MVP]
Obenstehender Code definiert die Klasse 'FileInfo', die von 'Object'
erbt, sowie eine Klasse 'SpecialFileInfo', die 'FileInfo' erweitert.
Nehmen wir nun an, Konstruktoren könnten vererbt werden. Dann würde
'FileInfo', wie 'Object', über einen parameterlosen Konstruktor verfügen.
Bei Shadows eben nicht.
Post by Herfried K. Wagner [MVP]
Nehmen wir weiters an, dass die Dokumentation zur
Eigenschaft 'FileName' der Klasse 'FileInfo' besagt, dass der bei der
Erstellung der Klasse angegebene Dateiname zurückgegeben wird und
ausserdem die weitere interne Logik der Klasse 'FileInfo' nur dann
funktioniert, wenn bereits im Konstruktor der Klasse 'm_FileName' auf
einen Pfad gesetzt wurde. Instanziert nun der Benutzer der Klasse
'FileInfo' mit dem von 'Object' geerbten, parameterlosen Konstruktor,
kann das zuvor Gesagte nicht mehr sichergestellt werden.
So etwas geht wegen Shadows nicht.

Peter
Herfried K. Wagner [MVP]
2005-01-03 11:48:58 UTC
Permalink
Hallo Peter!
Post by Peter Fleischer
Post by Herfried K. Wagner [MVP]
Beispiel?
Public Class Baseclass
Public Sub New()
' ...
End Sub
End Class
Public Class FileInfo
Inherits Baseclass
Private m_FileName As String
Public Shadows Sub New(ByVal FileName As String)
m_FileName = FileName
End Sub
Public ReadOnly Property FileName() As String
Get
Return m_FileName
End Get
End Property
End Class
Public Class SpecialFileInfo
Inherits FileInfo
Public Shadows Sub New()
MyBase.x("C:\AUTOEXEC.BAT")
End Sub
Public Shadows Sub New(ByVal FileName As String)
MyBase.x(FileName)
End Sub
End Class
Ich versteh's immer noch nicht. 'Sub New' kann nicht mit 'Shadows' markiert
werden.
--
M S Herfried K. Wagner
M V P <URL:http://dotnet.mvps.org/>
V B <URL:http://dotnet.mvps.org/dotnet/faqs/>
Peter Fleischer
2005-01-03 11:59:24 UTC
Permalink
Herfried K. Wagner [MVP] wrote:
...
Post by Herfried K. Wagner [MVP]
Ich versteh's immer noch nicht. 'Sub New' kann nicht mit 'Shadows'
markiert werden.
Herfried,
du hast doch angefangen mit: "Würden Konstruktoren geerbt werden, wäre
jedoch genau dies möglich, d.h. es kann zu inkonsistenten Objektzuständen
kommen. Betrachten wir dazu folgendes Beispiel:". Ich habe nur deine
"theoretische Betrachtung" weitergeführt:-)

Peter
Herfried K. Wagner [MVP]
2005-01-03 12:31:52 UTC
Permalink
Hallo Peter!
Post by Peter Fleischer
Post by Herfried K. Wagner [MVP]
Ich versteh's immer noch nicht. 'Sub New' kann nicht mit 'Shadows'
markiert werden.
du hast doch angefangen mit: "Würden Konstruktoren geerbt werden, wäre
jedoch genau dies möglich, d.h. es kann zu inkonsistenten Objektzuständen
kommen. Betrachten wir dazu folgendes Beispiel:". Ich habe nur deine
"theoretische Betrachtung" weitergeführt:-)
Achso...
--
M S Herfried K. Wagner
M V P <URL:http://dotnet.mvps.org/>
V B <URL:http://dotnet.mvps.org/dotnet/faqs/>
Peter Ramsebner
2005-01-02 18:21:41 UTC
Permalink
danke:)
Post by Herfried K. Wagner [MVP]
Hallo Peter!
Post by Peter Ramsebner
können Überladene Konstruktoren nicht vererbt werden?
Nein. Konstruktoren werden nicht vererbt, sondern müssen in der
abgeleiteten Klasse neu implementiert werden. Üblicherweise erfolgt dies
mit einem Aufruf des Konstruktors der Basisklasse, wenn Konstruktoren
\\\
Public Class Base
Public Sub New(ByVal i As Integer, ByVal s As String)
...
End Sub
End Class
Public Class Derived
Inherits Base
Public Sub New(ByVal i As Integer, ByVal s As String)
MyBase.New(i, s)
End Sub
End Class
///
Dass Konstruktoren nicht vererbt werden, ist keine sinnfreie Einschränkung
von .NET, sondern hat seine Ursache darin, dass eine abgeleitete Klasse
eventuell zusätzliche Daten zur Initialisierung benötigt, also bestehende
Konstruktoren für die Instanzierung/Initialisierung nicht ausreichend sein
können.
--
M S Herfried K. Wagner
M V P <URL:http://dotnet.mvps.org/>
V B <URL:http://dotnet.mvps.org/dotnet/faqs/>
Peter Fleischer
2005-01-02 19:13:39 UTC
Permalink
Herfried K. Wagner [MVP] wrote:
...
Post by Herfried K. Wagner [MVP]
Dass Konstruktoren nicht vererbt werden, ist keine sinnfreie
Einschränkung von .NET, sondern hat seine Ursache darin, dass eine
abgeleitete Klasse eventuell zusätzliche Daten zur Initialisierung
benötigt, also bestehende Konstruktoren für die
Instanzierung/Initialisierung nicht ausreichend sein können.
Herfried,
das ist Unsinn.

Ein Konstruktor ist eben keine Methode. In VB wird der Konstruktor der
Einfachkeit halber als Sub New bezeichnet, in C# aber nicht als void.
Während jede Methode beliebig oft aufgerufen werden kann, kann der
Konstruktur nur einmal in seiner Funktion als Konstruktor aufgerufen werden.
Daraus lassen sich auch die Bedingungen ableiten, unter denen eine erbende
Klasse einen Konstruktur enthalten muss, wenn die Basisklasse keinen
Standarkonstruktor hat.

Peter
Herfried K. Wagner [MVP]
2005-01-02 19:51:03 UTC
Permalink
Hallo Peter!
Post by Peter Fleischer
Post by Herfried K. Wagner [MVP]
Dass Konstruktoren nicht vererbt werden, ist keine sinnfreie
Einschränkung von .NET, sondern hat seine Ursache darin, dass eine
abgeleitete Klasse eventuell zusätzliche Daten zur Initialisierung
benötigt, also bestehende Konstruktoren für die
Instanzierung/Initialisierung nicht ausreichend sein können.
das ist Unsinn.
Warum sollte es das sein?

Zumindest stehe ich mit meiner Ansicht nicht alleine da (letzter Absatz):

<URL:http://www.yoda.arachsys.com/csharp/constructors.html>
-> "Constructors are not Inherited"
Post by Peter Fleischer
Ein Konstruktor ist eben keine Methode.
Das steht nicht im Widerspruch zu meiner Aussage.
Post by Peter Fleischer
In VB wird der Konstruktor der Einfachkeit halber als Sub New bezeichnet,
in C# aber nicht als void.
Schlussendlich ist es vollkommen egal, als was Konstruktoren bezeichnet
werden, wenn man weiss, was ein Konstruktor /tut/.
Post by Peter Fleischer
Während jede Methode beliebig oft aufgerufen werden kann, kann der
Konstruktur nur einmal in seiner Funktion als Konstruktor aufgerufen werden.
Das liegt in der Art, wie Konstruktoren spezifiziert sind. Technisch gesehen
würde nichts dagegen sprechen, Konstruktoren quasi "zu vererben", d.h. die
Programmiersprache dazu zu bringen, Konstruktoren der Basisklasse auch in
der abgeleiteten Klasse sichtbar zu machen, etwa, indem der Compiler
automatisch und vollkommen transparent für den Entwickler Code der Form

\\\
Public Sub New(ByVal i As Integer)
MyBase.New(i)
End Sub
///

(entsprechend allen in der Basisklasse vorhandenen Konstruktoren) generiert.
Post by Peter Fleischer
Daraus lassen sich auch die Bedingungen ableiten, unter denen eine erbende
Klasse einen Konstruktur enthalten muss, wenn die Basisklasse keinen
Standarkonstruktor hat.
Schon klar, das ein Konstruktor immer zu einer speziellen Klasse in der
Vererbungshierarchie gehört, und deshalb, falls in der Basisklasse kein
Standardkonstruktor vorhanden ist, selbst ein Konstruktor implementiert
werden muss, der den entsprechenden (parametrisierten) Konstruktor der
Basisklasse aufruft. Aber auch das ist nur /Folge/ dessen, dass VB nicht
automatisch Code erstellt, der den Entwickler glauben lässt, in Basisklassen
definierte Konstruktoren seien in der abgeleiteten Klasse "geerbt" worden.
--
M S Herfried K. Wagner
M V P <URL:http://dotnet.mvps.org/>
V B <URL:http://dotnet.mvps.org/dotnet/faqs/>
Peter Fleischer
2005-01-02 21:00:32 UTC
Permalink
Herfried K. Wagner [MVP] wrote:
...
Post by Herfried K. Wagner [MVP]
<URL:http://www.yoda.arachsys.com/csharp/constructors.html>
-> "Constructors are not Inherited"
Herfried,
das mag schon sein, dass auch noch mehr Anwender andere Vorstellungen von
der im Framework implementierten Philisophie haben. Es ist nun aber so
realisiert, weshalb deine Aussage in Bezug auf die konkrete Realisierung
eben in meinen Augen Unsinn ist:

<Zitat deines Beitrages>
Dass Konstruktoren nicht vererbt werden, ist keine sinnfreie Einschränkung
von .NET, sondern hat seine Ursache darin, dass eine abgeleitete Klasse
eventuell zusätzliche Daten zur Initialisierung benötigt, also bestehende
Konstruktoren für die Instanzierung/Initialisierung nicht ausreichend sein
können..
</Zitat>

Vor allem widerspricht dieser Beitrag deinen weiteren Ausführungen:

...
Post by Herfried K. Wagner [MVP]
Das liegt in der Art, wie Konstruktoren spezifiziert sind. Technisch
gesehen würde nichts dagegen sprechen, Konstruktoren quasi "zu
vererben", d.h. die Programmiersprache dazu zu bringen, Konstruktoren
der Basisklasse auch in der abgeleiteten Klasse sichtbar zu machen,
etwa, indem der Compiler automatisch und vollkommen transparent für
den Entwickler Code der Form
\\\
Public Sub New(ByVal i As Integer)
MyBase.New(i)
End Sub
///
(entsprechend allen in der Basisklasse vorhandenen Konstruktoren) generiert.
Peter
Herfried K. Wagner [MVP]
2005-01-02 21:31:33 UTC
Permalink
Hallo Peter!
Post by Peter Fleischer
Post by Herfried K. Wagner [MVP]
<URL:http://www.yoda.arachsys.com/csharp/constructors.html>
-> "Constructors are not Inherited"
das mag schon sein, dass auch noch mehr Anwender andere Vorstellungen von
der im Framework implementierten Philisophie haben. Es ist nun aber so
realisiert, weshalb deine Aussage in Bezug auf die konkrete Realisierung
Ich verstehe nicht ganz, was du meinst. Konstruktoren können in .NET nicht
vererbt werden, soweit sind wir uns ja einig. Ausserdem sind wir uns einig,
dass Konstruktoren weit mehr/etwas anders als normale Methoden sind. Mir ist
also nicht klar, wo an meiner Aussage du Kritik übst.
Post by Peter Fleischer
<Zitat deines Beitrages>
Dass Konstruktoren nicht vererbt werden, ist keine sinnfreie Einschränkung
von .NET, sondern hat seine Ursache darin, dass eine abgeleitete Klasse
eventuell zusätzliche Daten zur Initialisierung benötigt, also bestehende
Konstruktoren für die Instanzierung/Initialisierung nicht ausreichend sein
können..
</Zitat>
Das tut es nicht!
Post by Peter Fleischer
Post by Herfried K. Wagner [MVP]
Das liegt in der Art, wie Konstruktoren spezifiziert sind. Technisch
gesehen würde nichts dagegen sprechen, Konstruktoren quasi "zu
vererben", d.h. die Programmiersprache dazu zu bringen, Konstruktoren
der Basisklasse auch in der abgeleiteten Klasse sichtbar zu machen,
etwa, indem der Compiler automatisch und vollkommen transparent für
den Entwickler Code der Form
\\\
Public Sub New(ByVal i As Integer)
MyBase.New(i)
End Sub
///
(entsprechend allen in der Basisklasse vorhandenen Konstruktoren) generiert.
Wie steht das im Widerspruch zu meiner oben zitierten Aussage? Technisch
spricht nichts gegen eine Lösung, wie im zweiten Zitat angegeben, d.h.
Quasi-Vererbung von Konstruktoren könnte realisiert werden. Die andere Frage
ist, ob das sinnvoll wäre, und diese Frage ist, aus den im ersten Zitat
wiedergegebenen Gründen, mit "nein" zu beantworten. Siehe dazu auch mein
Beispiel mit 'FileInfo' im anderen Beitrag (Reaktion auf Haralds Beitrag).
--
M S Herfried K. Wagner
M V P <URL:http://dotnet.mvps.org/>
V B <URL:http://dotnet.mvps.org/dotnet/faqs/>
René Ziller
2005-01-03 06:22:54 UTC
Permalink
Post by Herfried K. Wagner [MVP]
\\\
Public Sub New(ByVal i As Integer)
MyBase.New(i)
End Sub
///
(entsprechend allen in der Basisklasse vorhandenen Konstruktoren) generiert.
Das sollte sich doch problemlos mit einem Makro/Addin lösen lassen,
oder?
--
René Ziller
Herfried K. Wagner [MVP]
2005-01-03 11:00:45 UTC
Permalink
Hallo Rene!
Post by René Ziller
Post by Herfried K. Wagner [MVP]
\\\
Public Sub New(ByVal i As Integer)
MyBase.New(i)
End Sub
///
(entsprechend allen in der Basisklasse vorhandenen Konstruktoren) generiert.
Das sollte sich doch problemlos mit einem Makro/Addin lösen lassen,
oder?
Ja, wenn man die Funktionalität haben will.
--
M S Herfried K. Wagner
M V P <URL:http://dotnet.mvps.org/>
V B <URL:http://dotnet.mvps.org/dotnet/faqs/>
Loading...