![]() |
Problem mit Vererbung
Ich wollte folgende Grundkronstruktion verwenden:
Delphi-Quellcode:
Nun soll es davon 2 verschiedene Tabtypen geben:
TTab = class(TObject)
private FSheet: TTabSheet; FTabs : TTabs; procedure SetSheet(const Value: TTabSheet); published property Sheet : TTabSheet read FSheet write SetSheet; property Tabs : TTabs read FTabs; public constructor Create(const APageControl : TPageControl); destructor Destroy; end;
Delphi-Quellcode:
Funktioniert soweit.
TMemoTab = class(TTab)
end; TExplorerTab = class(TTab) end; Nun habe ich auch eine Liste:
Delphi-Quellcode:
Nun soll TTab keine Funktionen haben.
TTabs = class(TObject)
private FTabs : TObjectList; end; Also habe ich alle Funktionen als "virtual; abstract;" bezeichnet. Wenn ich nun der Tabliste ein Tab hinzufüge mit folgender Funktion:
Delphi-Quellcode:
Dann gibt es dort einen Abstrakten Fehler.
procedure TTabs.Add(const ATab: TTab);
begin FTabs.Add(ATab); ATab.FTabs := self; end; Wenn ich nun die nicht als abstrakt bezeichne und "Quasileerfunktionen" einsetze, dann habe ich das Problem in der Add-Funktion, ATab nicht mehr "aktuell" ist. Folgender Aufruf (Tabs : TTabs):
Delphi-Quellcode:
Alles wunderbar... Jedenfalls scheint es so.
Tabs.Add(TExplorerTab.Create(pcTabs, CreatePath(Node)));
Wenn ich jetzt in der Add-Methode die Caption des TabSheets ändere, dann hat es keine Auswirkungen:
Delphi-Quellcode:
Wo liegt nun der Fehler?
procedure TTabs.Add(const ATab: TTab);
begin FTabs.Add(ATab); ATab.FSheet.Caption := 'BOM!'; // Oder auch so (Die Add-Methode darüber wird entfernt): (FTabs.Items[FTabs.Add(ATab)] as TTab).FSheet.Caption := 'BOM!'; ATab.FTabs := self; end; Wenn ihr noch Informationen braucht, dann sagt bitte welche, damit ich die nachliefern kann :) MfG xZise PS: Die TTabs Klasse:
Delphi-Quellcode:
TTabs = class(TObject)
private FTabs : TObjectList; FIcons : TIconList; FFileToolBar: TToolBar; FDirectoryToolBar: TToolBar; function GetTab(idx: Integer): TTab; procedure SetTab(idx: Integer; const Value: TTab); public property Tab[idx : Integer] : TTab read GetTab write SetTab; property FileToolBar : TToolBar read FFileToolBar write FFileToolBar; property DirectoryToolBar : TToolBar read FDirectoryToolBar write FDirectoryToolBar; procedure Add(const ATab : TTab); procedure Delete(const AIndex : Integer); constructor Create; destructor Destroy; override; end; |
Re: Problem mit Vererbung
Zitat:
|
Re: Problem mit Vererbung
außerdem hats du in TTab bereits FTabs deklariert, vielleicht kommt da was durcheinander?
|
Re: Problem mit Vererbung
Zitat:
Zitat:
Damit der Tab nachher "weis" in welcher Liste der gehört, um selber für die Tabliste Tabs zu erzeugen. Hier ist nochmal TTabs ^^
Delphi-Quellcode:
TTabs = class(TObject)
private FTabs : TObjectList; FIcons : TIconList; // wird nicht verwendet FFileToolBar: TToolBar; FDirectoryToolBar: TToolBar; function GetTab(idx: Integer): TTab; procedure SetTab(idx: Integer; const Value: TTab); public property Tab[idx : Integer] : TTab read GetTab write SetTab; property FileToolBar : TToolBar read FFileToolBar write FFileToolBar; property DirectoryToolBar : TToolBar read FDirectoryToolBar write FDirectoryToolBar; procedure Add(const ATab : TTab); procedure Delete(const AIndex : Integer); constructor Create; destructor Destroy; override; end; |
Re: Problem mit Vererbung
Zitat:
Zitat:
Das vergessene Override beim Destruktor hast du ja nun schon ergänzt... |
Re: Problem mit Vererbung
Hi,
Zitat:
Weil bei TStrings funktionierts ja auch :)
Delphi-Quellcode:
var
sl : TStrings; begin {...} sl := TStringList.Create; ini.ReadSections(sl); {...} end; Zitat:
Zitat:
MfG xZise |
Re: Problem mit Vererbung
Zitat:
Zitat:
Zitat:
|
Re: Problem mit Vererbung
Zitat:
Zitat:
Zitat:
So ! Ich habe jetzt TTab komplett "deabstrahiert" xD und die Add Methode überladen (mit TMemoTab und TExplorerTab) So funktionierts, aber das war nicht der Zweck des Vererben :) MfG xZise |
Re: Problem mit Vererbung
Zitat:
Zitat:
Zitat:
|
Re: Problem mit Vererbung
Meine Glaskugel meint, es könnten n paar override; fehlen...
mfg Christian |
Re: Problem mit Vererbung
Zitat:
|
Re: Problem mit Vererbung
Zitat:
Der abstrakte Fehler erscheint dann, wenn ich das alles als abstrakt deklariere nicht :) Zitat:
Zitat:
Hier ist der Konstruktor von TExplorerTab (ich spare mir mal TMemoTab): (Aufgrund von inherited auch von TTab)
Delphi-Quellcode:
constructor TExplorerTab.Create(const APageControl: TPageControl; const APath : string);
begin inherited Create(APageControl); FSheet := TSheet.Create(APageControl); FSheet.Caption := GetLastFolder(APath); FPath := APath; // Icons einlesen FImages := TImageList.Create(APageControl); FImages.Width := 32; FImages.Height := 32; ConvertTo32BitImageList(FImages); FExt := TStringList.Create; FExt.Add('folder'); FImages.AddIcon(GetIconFromFile('%SystemRoot%\system32\SHELL32.dll', 3)); FSheet.lvListView.LargeImages := FImages; FSheet.lvListView.OnDblClick := DblClick; FSheet.lvListView.OnMouseUp := MouseUp; GenerateView; end; constructor TTab.Create(const APageControl: TPageControl); begin inherited Create; end; Zitat:
|
Re: Problem mit Vererbung
Wozu bekommt der Konstruktor von TTab ein TPageControl übergeben, wenn er nichts damit macht? Auch TExplorerTab macht nichts damit als es nur weiter zu reichen.
Zitat:
|
Re: Problem mit Vererbung
Hi,
Zitat:
[edit]so :) Ich habe jetzt von TTab die Konstruktor Methode entfernt, und es ändert sich NICHTS :) Vielleicht ist es wichtig, dass es mit Überladen funktioniert?[/edit] Zitat:
MfG xZise |
Re: Problem mit Vererbung
Ich kann das einfach nicht glauben. Das sind grundlegende OOP Dinge und das kann sich nicht so beschissen verhalten. Würde etwas dagegen sprechen, wenn man selber mal den Quelltext als ganzen beschauen kann? Ich komm nicht damit klar, dass das nicht gehen sollte...
|
Re: Problem mit Vererbung
Okay hier mal der Code ;) Ich habe unwichtiges soweit ein bisschen entfernt.
Der aufruf (s.o.) erfolg weiterhin mit:
Delphi-Quellcode:
Hier ist die Unit! Aber mit TntControls.
<TTabs>.Add(<TExplorer/TMemoTab>.Create(<PageControl>, <Pfad/Dateiname>))
TSheets ist ein Nachfahre von TabSheet mit ein paar Komponenten drauf. Ich hoffe mal das reicht :)
Delphi-Quellcode:
unit uCode;
interface uses Windows, ComCtrls, SysUtils, Classes, Contnrs, uTabSheet, ShellAPI, Graphics, Controls, TntIniFiles, TntStdCtrls, StdCtrls, TntComCtrls; type TData = (dFile, dDirectory); TTabs = class; TTab = class(TObject) private FSheet: TTabSheet; FTabs : TTabs; procedure SetSheet(const Value: TTabSheet);// virtual; abstract; published property Sheet : TTabSheet read FSheet write SetSheet; property Tabs : TTabs read FTabs; public //constructor Create(const APageControl : TPageControl);// virtual; abstract; destructor Destroy; override;// virtual; abstract; end; TMemoTab = class(TTab) private FFileName : string; FMemo : TTntMemo; procedure SetMemo(const Value: TTntMemo); // procedure DblClick(Sender : TObject); // procedure MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); published property FileName : string read FFileName; property Memo : TTntMemo read FMemo write SetMemo; public constructor Create(const APageControl : TPageControl; const AFileName : string); reintroduce; destructor Destroy; override; end; TExplorerTab = class(TTab) private FImages : TImageList; FExt : TStringList; FSheet: TSheet; FTabs : TTabs; FPath : string; FData : array of TData; procedure DblClick(Sender : TObject); procedure MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure SetSheet(const Value: TSheet); procedure GenerateView(const AFilter : string = '*.*'); published property Path : string read FPath; property Sheet : TSheet read FSheet write SetSheet; property Tabs : TTabs read FTabs; public procedure GoUp; constructor Create(const APageControl : TPageControl; const APath : string); reintroduce; destructor Destroy; override; end; TTabs = class(TObject) private FTabs : TObjectList; FIcons : TIconList; FFileToolBar: TToolBar; FDirectoryToolBar: TToolBar; function GetTab(idx: Integer): TTab; procedure SetTab(idx: Integer; const Value: TTab); public property Tab[idx : Integer] : TTab read GetTab write SetTab; property FileToolBar : TToolBar read FFileToolBar write FFileToolBar; property DirectoryToolBar : TToolBar read FDirectoryToolBar write FDirectoryToolBar; procedure Add(ATab : TTab); overload; procedure Delete(const AIndex : Integer); constructor Create; destructor Destroy; override; end; implementation uses ImgList, Consts, CommCtrl; Procedure ConvertTo32BitImageList(Const ImageList: TImageList); Const Mask: Array[Boolean] Of Longint = (0, ILC_MASK); Var TemporyImageList: TImageList; Begin If Assigned(ImageList) Then Begin TemporyImageList := TImageList.Create(Nil); Try TemporyImageList.Assign(ImageList); With ImageList Do Begin ImageList.Handle := ImageList_Create(Width, Height, ILC_COLOR32 Or Mask[Masked], 0, AllocBy); If Not ImageList.HandleAllocated Then Begin Raise EInvalidOperation.Create(SInvalidImageList); End; End; ImageList.AddImages(TemporyImageList); Finally TemporyImageList.Free; End; End; End; function GetFileIcon(const FileName: string; const Icon: TIcon; const FileMustExist: Boolean): Boolean; var FI: TSHFileInfo; Attributes: DWORD; Flags: Word; begin if FileMustExist then begin Attributes := 0; Flags := SHGFI_ICON or SHGFI_LARGEICON; end else begin Attributes := FILE_ATTRIBUTE_NORMAL; Flags := SHGFI_USEFILEATTRIBUTES or SHGFI_ICON or SHGFI_LARGEICON; end; if SHGetFileInfo(PChar(FileName), Attributes, FI, SizeOf(FI), Flags) <> 0 then begin Icon.ReleaseHandle; Icon.Handle := FI.hIcon; Result := True; end else Result := False; end; function GetIconFromFile(FileName: string; Index: Integer): Ticon; begin Result := TIcon.Create; Result.Handle := ExtractIcon(HInstance, PCHAR(FileName), Index); end; function GetIconFromFile2(const Path: String): TIcon; var KommaPos, Len, IconNumber: Integer; begin Len := Length(Path); KommaPos := LastDelimiter(',', Path); IconNumber := StrToInt(copy(Path,KommaPos + 1, Len)); Result := GetIconFromFile(Copy(Path, 1, KommaPos - 1), IconNumber); end; function GetLastFolder(const APath : string) : string; var i, start: Integer; begin if APath[Length(APath)] = '\' then start := 1 else start := 0; for i := Length(APath) - start downto 1 do begin if APath[i] <> '\' then Result := APath[i] + Result else break; end; end; { TExplorerTab } constructor TExplorerTab.Create(const APageControl: TPageControl; const APath : string); begin inherited Create; FSheet := TSheet.Create(APageControl); FSheet.Caption := GetLastFolder(APath); FPath := APath; // Icons einlesen FImages := TImageList.Create(APageControl); FImages.Width := 32; FImages.Height := 32; ConvertTo32BitImageList(FImages); FExt := TStringList.Create; FExt.Add('folder'); FImages.AddIcon(GetIconFromFile('%SystemRoot%\system32\SHELL32.dll', 3)); FSheet.lvListView.LargeImages := FImages; FSheet.lvListView.OnDblClick := DblClick; FSheet.lvListView.OnMouseUp := MouseUp; GenerateView; end; procedure TExplorerTab.DblClick(Sender: TObject); begin // Beep; if FData[FSheet.lvListView.ItemIndex] = dDirectory then begin FPath := FPath + FSheet.lvListView.Selected.Caption + '\'; FSheet.Caption := GetLastFolder(FPath); GenerateView; end; end; destructor TExplorerTab.Destroy; begin FreeAndNil(FImages); FreeAndNil(FExt); inherited; end; procedure TExplorerTab.GenerateView(const AFilter : string); begin {...} end; procedure TExplorerTab.GoUp; begin {...} end; procedure TExplorerTab.MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin {...} end; procedure TExplorerTab.SetSheet(const Value: TSheet); begin FSheet := Value; end; { TTabs } procedure TTabs.Add(ATab: TTab); begin FTabs.Add(ATab); ATab.FTabs := self; end; constructor TTabs.Create; begin inherited; FTabs := TObjectList.Create; FIcons := TIconList.Create; end; procedure TTabs.Delete(const AIndex: Integer); begin if AIndex >= 0 then FTabs.Delete(AIndex); end; destructor TTabs.Destroy; begin FreeAndNil(FTabs); inherited; end; function TTabs.GetTab(idx: Integer): TTab; begin if idx >= 0 then Result := TTab(FTabs[idx]) else Result := nil; end; procedure TTabs.SetTab(idx: Integer; const Value: TTab); begin FTabs[idx] := Value; end; { TMemoTab } constructor TMemoTab.Create(const APageControl: TPageControl; const AFileName: string); begin inherited Create; FSheet := TTabSheet.Create(APageControl.Owner); FSheet.PageControl := APageControl; FSheet.Caption := ExtractFileName(AFileName); FMemo := TTntMemo.Create(APageControl.Owner); FMemo.Parent := FSheet; FMemo.Align := alClient; FMemo.ScrollBars := ssBoth; FMemo.WordWrap := false; FMemo.Lines.LoadFromFile(AFileName); end; destructor TMemoTab.Destroy; begin FreeAndNil(FMemo); inherited; end; procedure TMemoTab.SetMemo(const Value: TTntMemo); begin FMemo := Value; end; { TTab } destructor TTab.Destroy; begin FreeAndNil(FSheet); inherited; end; procedure TTab.SetSheet(const Value: TTabSheet); begin FSheet := Value; end; end. |
Re: Problem mit Vererbung
Moin!
Grundlegend ist zZ vieles recht komisch. Ein abstrakt virtueller Constructor ist nun schon wirklich recht speziell (ok, wird zZ nicht genutzt), aber auch ein Overload bei der Add() Methode ist noch übrig, aber das tut auch nichts zur Sache. ABER: Du hast zwei unterschiedliche Definitionen von Sheet. Einmal in der Basis und einmal in einer Ableitung. Das recht komische dabei ist dabei, dass du unterschiedliche Klassen verwendest. Dazu kommt noch, dass du die Instanz in der Ableitung erstellst aber in der Basis freigibst. Und zu deinem NIL Problem: Du greifst auf fSheet zu, wobei du eine Variable vom Typ TTab nutzt. Dadurch greifst du auf den Typ von Sheet von TTab zu. Da du aber in der Ableitung einen neuen Typ definierst (und eine neue Variable) aber die Basisklasse nutzt zum Zugriff, bekommst du fSheet von der Basis TTab - und die ist natürlich nil (schliesslich initialisierst du es nicht in TTab). Wenn du nun den Typ nicht neu definieren würdest in der Ableitung, dann hättest du Sheet vererbt und dann wäre beim Zugriff über TTab auch die Instanz von TExplorerTab zu finden - es gibt schliesslich nur noch ein Tab. Aber das du die alte Eigenschaft verdeckst und eine neue deklarierst, hättest du aber wirklich mal sagen können. Schliesslich hat das ganze Problem nachweislich nichts virtual & | abstract zu tun. Also: dein Weg ist wie beschrieben begehbar - ABER: einige dich auf einen Typ... Live long and prosper, Locutus! |
Re: Problem mit Vererbung
Zitat:
Zitat:
Zitat:
Zitat:
Zitat:
Zitat:
Also werde ich wohl einer der einzigen Gemeinsamkeit entfernen :( OBWOHL :) müsste es nicht gehen, wenn ich einfach den FSheet : TSheet entferne (und die Prozedur/Property) müsste es doch laufen :) Gleich mal ausprobieren xD Zitat:
Zitat:
Zitat:
|
Re: Problem mit Vererbung
Zitat:
Zitat:
Zitat:
Zitat:
Zitat:
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:36 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz