2016-06-22 24 views
2

In meiner Anwendung muss die Steuerelemente von Drittanbietern um zusätzliche Funktionen erweitert werden.Hinzufügen von Feldern und Methoden zu Klassen, die von derselben Basis erben, ohne die Basisklasse zu ändern

Ein Beispiel wäre TcxLabel und TcxDBLabel (von DevExpress). Beide erben von der gleichen Basisklasse.

Für diese Steuerelemente möchte ich einige Felder und Methoden hinzufügen.

Die Art, wie ich es heute tun:

TMycxLabel = class(TcxLabel) 
private 
    FMyField1: string; 
    FMyField2: Integer; 
public 
    procedure DoSomething; 
end; 

TMycxDBLabel = class(TcxDBLabel) 
private 
    FMyField1: string; 
    FMyField2: Integer; 
public 
    procedure DoSomething; 
end; 

Also im Grunde muss ich alles doppelt schreiben.

Eine Möglichkeit, dies zu erreichen, wäre die Änderung der Basisklasse, von der 2 Steuerelemente erben. Aber das ist keine Option - die DevExpress-Klassen/-Pakete sollten nicht geändert werden.

Gibt es eine Möglichkeit, dies zu erreichen?

+0

AFAIK gibt es keinen sauberen Weg, dies zu tun. –

+1

@MartynA Klassenhelfer erlauben es mir nicht, neue Felder, nur Methoden zu deklarieren. – Thomas

+0

Ach ja, tut mir leid, ich hatte einen "Senior Moment". – MartynA

Antwort

2

Gibt es eine Möglichkeit, dies zu erreichen?

Nein, gibt es nicht. Jede praktikable Lösung entspricht im Wesentlichen Ihrer derzeitigen Vorgehensweise. Da Sie den Zustand, der der Instanz zugeordnet ist, möchten, benötigen Sie ihn realistisch als Teil der Instanz. Was führt Sie zu der Lösung, die Sie haben.

Sie könnten erwägen ein Feld wie Tag zu entführen, um diesen Zustand zu speichern, aber das wäre falsch, weil Tag für die Verwendung durch den Verbraucher des Typs reserviert ist. Andere plausible Lösungen könnten beinhalten, eine separate Liste zu führen, die die Instanz diesem zusätzlichen Zustand zuordnet. Sie könnten diese Arbeit machen, aber meiner Meinung nach wäre es so unhandlich, schlimmer zu sein als die Alternative.

Der effektivste Ansatz wäre, die Felder zu einer gemeinsamen Basisklasse hinzuzufügen, aber Sie haben dies ausgeschlossen, da Code von Drittanbietern geändert wird.

0

Konnten Sie einmal zu einer virtuellen Klasse erben (die "Ihre" ist), definieren Sie die neuen Felder dort, dann erben Sie die zwei neuen Klassen von dort?

bearbeiten basierend auf Kommentare:

gut Sie smth wie diese versuchen könnte.

in beiden Ihre geerbten Klassen, fügen Sie einfach ein öffentliches Datenelement, das selbst eine Klasse ist, wo Sie Ihre eigenen Sachen definieren ... sieht aus wie:

TMycxLabel = class(TcxLabel) 
public 
    MyStuff: TMyStuff; 
end; 

TMyStuff = class() 
private 
    FMyField1: string; 
    FMyField2: Integer; 
public 
    procedure DoSomething; 
end; 

es dann nennen wie

cxLabel1.MyStuff.DoSomething(); 

Ich weiß, dass dies Ihre Frage nicht vollständig beantwortet und nicht für mehrere Anwendungsfälle funktioniert (Sie können nicht auf alle Attribute von TMycxLabel von MyStuff auf diese Weise zugreifen), aber vielleicht können Sie einige Doppelcodierung vermeiden.

+0

Wenn Sie versuchen, diese Idee mit etwas Code zu füllen, werden Sie feststellen, dass es nicht praktikabel ist. –

+0

Nun, ich war verwirrt über die "gleiche Basisklasse" in der Betreffzeile. Anscheinend erbt er von zwei Basisklassen. – Jur

+0

@Jur: Ja, er erbt von den beiden erwähnten Klassen. Aber diese beiden stammen von derselben Basisklasse ab. –

1

Es gibt einen Weg, obwohl es nur dient, wenn Sie nur brauchen, was in der Basisklasse verfügbar ist. Zum Beispiel, wenn TcxDBLabel von TcxLabel erbt, können Sie eine Methode (locker gesagt) zu beiden hinzufügen, solange Sie nur den TcxLabel Teil (Felder, Methoden und Eigenschaften) von TcxDBLabel verwenden.

Ich beziehe mich auf typecasting.

Ich sollte warnen, dass die Verwendung dieser Praxis nicht einvernehmlich ist. Viele Entwickler betrachten Typcasting als eine schlechte Praxis, und ich selbst tendiere dazu, es nur als letzten Ausweg zu verwenden. Ich überlasse Ihnen jedoch die philosophische Diskussion des Wetters, das Sie verwenden sollten oder nicht sollten.

Also, wenn Sie erstellen eine Unterklasse wie folgt aus:

THcxLabel = Class(TcxLabel) 
private 
    FMyField1: string; 
    FMyField2: Integer; 
public 
    procedure DoSomething; 
End; 

Anschließend können Sie diese in den beliebigen TcxLabel basierte Klasseninstanz, etwa so:

THcxLabel(cxLabel1).DoSomething; 
THcxLabel(cxDBLabel1).DoSomething; 

Wie ich schon sagte, keine Besonderheiten von TcxDBLabel wird Ihnen in der DoSomething-Methode zur Verfügung stehen, Sie können jedoch die Ressourcen der Basisklasse verwenden.