AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Virtuelle Methode überladen

Ein Thema von Nersgatt · begonnen am 4. Aug 2014 · letzter Beitrag vom 4. Aug 2014
Antwort Antwort
Benutzerbild von Nersgatt
Nersgatt

Registriert seit: 12. Sep 2008
Ort: Emlichheim
693 Beiträge
 
Delphi 10.1 Berlin Professional
 
#1

Virtuelle Methode überladen

  Alt 4. Aug 2014, 07:21
Moin,

ich habe folgendes Konstrukt:
Delphi-Quellcode:
  TClass1 = class
  public
    procedure DoSomething; virtual;
  end;

  TClass2 = class(TClass1)
  public
    procedure DoSomething(AText : String); overload;
  end;
Beim Compilieren bekomme ich die Warnung: [dcc32 Warnung] Unit7.pas(17): W1010 Methode 'DoSomething' verbirgt virtuelle Methode vom Basistyp 'TClass1'

Ich verstehe nicht, warum das so ist. Die Deklaration von TClass2.DoSomething unterscheidet sich doch von TClass1.DoSomething (es wird ja nur eine Überladung hinzugefügt). Warum wird dann die Methode aus TClass1 verborgen? Und wie kann ich das verhindern?

Danke!
Jens
  Mit Zitat antworten Zitat
bepe

Registriert seit: 17. Okt 2006
118 Beiträge
 
#2

AW: Virtuelle Methode überladen

  Alt 4. Aug 2014, 07:37
Überladen wird innerhalb einer Klasse:

Delphi-Quellcode:
  TClass1 = class
   public
     procedure DoSomething; virtual; overload
     procedure DoSomething(AText : String); overload;
   end;
Möchtest du die Signatur in einer erbenden Klasse ändern musst du reintroduce benutzen:

Delphi-Quellcode:
  TClass1 = class
   public
     procedure DoSomething; virtual;
   end;

   TClass2 = class(TClass1)
   public
     procedure DoSomething(AText : String); reintroduce; // hier wird die Signatur nur geändert aber keine zweite Variante eingeführt
     procedure DoSomething(AText : String); reintroduce; overload // Hier wird eine zweite Variante definiert; entspricht overload innerhalb einer Klasse
   end;

mfg,
bp
  Mit Zitat antworten Zitat
Dejan Vu
(Gast)

n/a Beiträge
 
#3

AW: Virtuelle Methode überladen

  Alt 4. Aug 2014, 07:41
Ich verstehe nicht, warum das so ist. Die Deklaration von TClass2.DoSomething unterscheidet sich doch von TClass1.DoSomething (es wird ja nur eine Überladung hinzugefügt). Warum wird dann die Methode aus TClass1 verborgen? Und wie kann ich das verhindern?
Rein theoretisch würde ich das auch nicht verstehen, aber in der Praxis musst Du die überladene Methode auch in der Grundklasse deklarieren.

Wenn das keine rein theoretische Frage ist, dann könnte das ein Hinweis auf ein schlechtes Design sein. Meistens findet man ein 'Workaround', d.h. eine Umformulierung des Codes, der sich im Nachhinein als sauberer herausstellt. Wieso z.B. muss die neue Methode genauso heißen? Macht sie wirklich das Gleiche?

@bepe: Ist dann in TClass2 auch 'DoSomething()' bekannt?
  Mit Zitat antworten Zitat
samso

Registriert seit: 29. Mär 2009
439 Beiträge
 
#4

AW: Virtuelle Methode überladen

  Alt 4. Aug 2014, 07:46
Falls Du DoSomething nur zusätzlich mit einem Parameter versehen willst, braucht sie nicht virtuell zu sein:

Delphi-Quellcode:
  TClass1 = class
  public
    procedure DoSomething; overload;
  end;

  TClass2 = class(TClass1)
  public
    procedure DoSomething(AText : String); overload;
  end;
Falls Du später auch noch überladen willst, ist das so möglich:

Delphi-Quellcode:
  TClass1 = class
  public
    procedure DoSomething; overload; virtual;
  end;

  TClass2 = class(TClass1)
  public
    procedure DoSomething(AText : String); overload;
  end;
  Mit Zitat antworten Zitat
Benutzerbild von Nersgatt
Nersgatt

Registriert seit: 12. Sep 2008
Ort: Emlichheim
693 Beiträge
 
Delphi 10.1 Berlin Professional
 
#5

AW: Virtuelle Methode überladen

  Alt 4. Aug 2014, 07:57
Vielen Dank für die Erklärung. Mit reintroduce funktioniert es wie gewünscht. Damit wäre meine Frage erledigt.

Jetzt kommt der philosophische Teil, wo über den besten Weg diskutiert werden darf
Wenn das keine rein theoretische Frage ist, dann könnte das ein Hinweis auf ein schlechtes Design sein. Meistens findet man ein 'Workaround', d.h. eine Umformulierung des Codes, der sich im Nachhinein als sauberer herausstellt. Wieso z.B. muss die neue Methode genauso heißen? Macht sie wirklich das Gleiche?
Sie macht das Gleiche und noch ein bisschen mehr.

Ich könnte sie auch umbenennen, wobei ich mich frage, ob das in diesem Fall sauberer wäre.

Hier der "echte" Fall: es geht um die UniDac-Komponenten. Dazu gibt es den Sql-Monitor, der alle Sql-Anfragen, die von den Komponenten Richtung Server geschickt werden, ausgibt. Das ist sehr praktisch für Debuggingzwecke.
Die Connection bietet die Methode "MonitorMessage", mit der ich eine eigene Meldung im Sql-Monitor ausgeben kann (auch zu Debugzwecken manchmal hilfreich).

Die wollte ich nun mit dem Transactionhandling verbinden:
Delphi-Quellcode:
  TmyConnection = class(TUniConnection)
  private
    { Private-Deklarationen }
  protected
    { Protected-Deklarationen }
  public
    procedure StartTransaction(ASqlMonitorMessage : String); overload;
    procedure Commit (ASqlMonitorMessage : String); reintroduce; overload;
    procedure Rollback (ASqlMonitorMessage : String); reintroduce; overload;
  published
    { Published-Deklarationen }
  end;
Was dann entsprechend so implementiert ist:
Delphi-Quellcode:
procedure TmyConnection.Commit(ASqlMonitorMessage: String);
begin
  MonitorMessage('<< Committing Transaction: ' + ASqlMonitorMessage);
  Commit;
end;

procedure TmyConnection.Rollback(ASqlMonitorMessage: String);
begin
  MonitorMessage('!! Rolling back Transaction: ' + ASqlMonitorMessage);
  Rollback;
end;

procedure TmyConnection.StartTransaction(ASqlMonitorMessage: String);
begin
  MonitorMessage('>> Starting Transaction: ' + ASqlMonitorMessage);
  inherited StartTransaction;
end;
nun kann ich in TmyConnection.StartTransaction/Commit/Rollback einen eigenen Text mitgeben, der für die Fehlersuche (insbesondere beim Kunden, wo ich kein Delphi installiert hab) hilfreich sein soll.

Ich hätte natürlich auch die Methoden "StartTransactionWithMessage" oder so nennen können. Aber wäre das hier sinnvoll/sauber?
Ist sicher Ansichtssache.
Jens
  Mit Zitat antworten Zitat
Benutzerbild von Nersgatt
Nersgatt

Registriert seit: 12. Sep 2008
Ort: Emlichheim
693 Beiträge
 
Delphi 10.1 Berlin Professional
 
#6

AW: Virtuelle Methode überladen

  Alt 4. Aug 2014, 07:58
Falls Du DoSomething nur zusätzlich mit einem Parameter versehen willst, braucht sie nicht virtuell zu sein:
Das hat sich jetzt leider überschnitten. Wie Du an meinem vorherigen Post siehst, stammt TClass1 von einer Fremdkomponente. Daher ist die hier als gegeben anzusehen.
Jens
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
9.332 Beiträge
 
Delphi 11 Alexandria
 
#7

AW: Virtuelle Methode überladen

  Alt 4. Aug 2014, 11:01
Nur so nebenbei, weil ich es in deinem Quelltext sehe:
Bei Interfaces und Strings macht es auf jeden Fall Sinn grundsätzlich bei Parametern const zu übergeben, da ansonsten dort jedesmal die Referenzzählung anspringt. Das ist zwar performancemäßig nicht spürbar, wenn solche Methoden nicht sehr oft aufgerufen werden, ist aber dennoch unnötig.
Den Unterschied siehst du im Anhang, so klein ist er nicht...
Miniaturansicht angehängter Grafiken
asmrefcount.png  
Sebastian Jänicke
Alle eigenen Projekte sind eingestellt, ebenso meine Homepage, Downloadlinks usw. im Forum bleiben aktiv!
  Mit Zitat antworten Zitat
Dejan Vu
(Gast)

n/a Beiträge
 
#8

AW: Virtuelle Methode überladen

  Alt 4. Aug 2014, 13:23
Aber wäre das hier sinnvoll/sauber?
Ist sicher Ansichtssache.
Der Designfehler liegt dann nicht bei Dir. Hier würde ich aber eine Wrapperklasse implementieren, die die TUniConnection intern verwendet. Der kannst Du dann deine eigene saubere Schnittstelle verpassen, mit overload etc.

Note: Overload finde ich fast immer Blödsinn. Ich würde hier nur eine Methode à la
Procedure Commit (const aSQLMessage : String = ""); anbieten. Aber auch das ist Ansichtssache.
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 03:19 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz