-
Content Count
57 -
Joined
-
Last visited
Everything posted by bravesofts
-
i have base interface: type iBaseFoo = interface BaseMethod1; BaseMethod2; BaseMethod3; end; iTestFoo = interface(ibaseFoo) TestFooMethod; end; -- TBaseFoo = class(TInterfacedObject, iBaseFoo) private // some code here protected BaseMethod1; BaseMethod2; BaseMethod3; end; TTestFoo = class(TBaseFoo, ITestFoo) // how to Ensures TTestFoo inherits IBaseFoo methods from TBaseFoo, avoiding re-implementation. procedure TestFooMethod; end; -- my question is: How can I ensure that TTestFoo (or any descendant of TBaseFoo) uses the IBaseFoo method implementations provided by TBaseFoo, without re-implementing these methods in every descendant class?
- 14 replies
-
- code reuse
- class hierarchy
- (and 3 more)
-
inheritance Ensuring Consistent Base Interface Implementation in Delphi Class Hierarchy
bravesofts replied to bravesofts's topic in Algorithms, Data Structures and Class Design
I finally managed to update the code to exactly what I needed: My Github Updated Example- 14 replies
-
- code reuse
- class hierarchy
- (and 3 more)
-
inheritance Ensuring Consistent Base Interface Implementation in Delphi Class Hierarchy
bravesofts replied to bravesofts's topic in Algorithms, Data Structures and Class Design
I guess I'm not okay today, haha. Maybe I'm just lacking coffee or in need of some rest. Anyway, thank you, everyone!- 14 replies
-
- code reuse
- class hierarchy
- (and 3 more)
-
inheritance Ensuring Consistent Base Interface Implementation in Delphi Class Hierarchy
bravesofts replied to bravesofts's topic in Algorithms, Data Structures and Class Design
I apologize for the delay and also for the code full of errors above. I hope this example is easy to understand. Thank you Github Example Link- 14 replies
-
- code reuse
- class hierarchy
- (and 3 more)
-
inheritance Ensuring Consistent Base Interface Implementation in Delphi Class Hierarchy
bravesofts replied to bravesofts's topic in Algorithms, Data Structures and Class Design
Give me a maximum of an hour; I'm working on it and will provide a very simple, working example that can be easily understood- 14 replies
-
- code reuse
- class hierarchy
- (and 3 more)
-
inheritance Ensuring Consistent Base Interface Implementation in Delphi Class Hierarchy
bravesofts replied to bravesofts's topic in Algorithms, Data Structures and Class Design
I understand the code above is a bit long, but I’d like to keep it to ensure the example can be compiled fully. It provides the necessary context for the issue. If you don’t mind, I’d prefer to leave it here.- 14 replies
-
- code reuse
- class hierarchy
- (and 3 more)
-
inheritance Ensuring Consistent Base Interface Implementation in Delphi Class Hierarchy
bravesofts replied to bravesofts's topic in Algorithms, Data Structures and Class Design
unit Model.DB.Exceptions; interface uses System.SysUtils; type EDatabaseError = class(Exception); EInvalidParameterError = class(EDatabaseError); EConnectionError = class(EDatabaseError); implementation end. ---- Unit Model.Firedac.ParamsTypes; interface uses System.Classes, System.Generics.Collections; type {$REGION ' Firedac Connection Params .. '} {$REGION ' DriverName Param & DataType .. '} TDriverFDTypeEnum = (dtAccessDB, dtSqlite, dtPostgreSql, dtMySQL, dtFirebird, dtInterbase, dtInterbaseLite); TDriverFDTypeEnumHelper = record helper for TDriverFDTypeEnum public function ToString: string; function GetDriverName: string; end; TBaseFiredacDriver = class protected class function DBName(const aValue: TDriverFDTypeEnum): string; static; class function DriverName(const aValue: TDriverFDTypeEnum): string; static; end; TMSAccessDriver = class(TBaseFiredacDriver) end; TSQLiteDriver = class(TBaseFiredacDriver) end; TPostgreSqlDriver = class(TBaseFiredacDriver) end; TMySQLDriver = class(TBaseFiredacDriver) end; TFirebirdDriver = class(TBaseFiredacDriver) end; TInterbaseDriver = class(TBaseFiredacDriver) end; TInterbaseLiteDriver = class(TBaseFiredacDriver) end; {$ENDREGION} {$REGION ' SQLite Params .. '} TSQLiteLockingMode = (mLockingExclusive, mLockingNormal); TSQLiteLockingModeHelper = record helper for TSQLiteLockingMode public function ToString: string; end; TSQLiteEncryptMode = (EncryptNone, AES128, AES192, AES256, AES_CTR128, AES_CTR192, AES_CTR256, AES_ECB128, AES_ECB192, AES_ECB256); TSQLiteEncryptModeHelper = record helper for TSQLiteEncryptMode public function ToString: string; class function FromString(const aValue: string): TSQLiteEncryptMode; static; end; {$ENDREGION} TFDRemoteBy = (FlatFile, Remote, Custom); TFDRemoteByHelper = record helper for TFDRemoteBy public function ToString: string; end; {$ENDREGION} implementation uses System.SysUtils, Model.DB.Exceptions; {$REGION ' Driver FireDac Type Helper.. '} function TDriverFDTypeEnumHelper.ToString: string; const cDBTypeNames: array [TDriverFDTypeEnum] of string = ( 'MSAccess', 'SQLite', 'PostgreSQL', 'MySQL', 'Firebird', 'Interbase', 'Interbase Lite' ); begin Result := cDBTypeNames[Self]; end; function TDriverFDTypeEnumHelper.GetDriverName: string; const cDBDriverNames: array [TDriverFDTypeEnum] of string = ( 'MSAcc', 'SQLite', 'PG', 'MySQL', 'FB', 'IB', 'IBLite' ); begin Result := cDBDriverNames[Self]; end; {$ENDREGION} {$REGION ' SQLite Locking Mode Helper .. '} function TSQLiteLockingModeHelper.ToString: string; const cLockingModeNames: array [TSQLiteLockingMode] of string = ( 'Exclusive','Normal' ); begin Result := cLockingModeNames[Self]; end; {$ENDREGION} {$REGION ' SQLite Encrypt Mode Helper .. '} function TSQLiteEncryptModeHelper.ToString: string; const cEncryptModeNames: array [TSQLiteEncryptMode] of string = ( 'No', 'aes-128', 'aes-192', 'aes-256', 'aes-ctr-128', 'aes-ctr-192', 'aes-ctr-256', 'aes-ecb-128', 'aes-ecb-192', 'aes-ecb-256' ); begin Result := cEncryptModeNames[Self]; end; class function TSQLiteEncryptModeHelper.FromString(const aValue: string): TSQLiteEncryptMode; var LEncryptMode: TSQLiteEncryptMode; begin for LEncryptMode := Low(TSQLiteEncryptMode) to High(TSQLiteEncryptMode) do if SameText(aValue, LEncryptMode.ToString) then Exit(LEncryptMode); raise EInvalidParameterError.CreateFmt('Invalid encryption mode: %s', [aValue]); end; {$ENDREGION} {$REGION ' FireDac RemoteBy Helper .. '} function TFDRemoteByHelper.ToString: string; const cFDRemoteByNames: array [TFDRemoteBy] of string = ( 'FlateFile', 'Remote', 'Custom' ); begin Result := cFDRemoteByNames[Self]; end; {$ENDREGION} { TBaseFiredacDriver } class function TBaseFiredacDriver.DBName( const aValue: TDriverFDTypeEnum): string; begin Result := aValue.ToString; end; class function TBaseFiredacDriver.DriverName( const aValue: TDriverFDTypeEnum): string; begin Result := aValue.GetDriverName; end; end. ---- unit Model.FiredacParams.BaseInterface; interface uses Model.Firedac.ParamsTypes; type iBaseFDParams<TDBType: TBaseFiredacDriver> = interface ['{B5A4A031-EFA0-4424-902D-2529FC4F1B48}'] function Pooled(aValue: Boolean): iBaseFDParams<TDBType>; overload; function Database(aValue: string): iBaseFDParams<TDBType>; overload; function Username(aValue: string): iBaseFDParams<TDBType>; overload; function Password(aValue: string): iBaseFDParams<TDBType>; overload; // function MonitorBy(aValue: TFDRemoteBy): iBaseFDParams<TDriverFDType>; overload; function Pooled: Boolean; overload; function Database: string; overload; function UserName: string; overload; function Password: string; overload; // function MonitorBy: TFDRemoteBy; overload; function Params: iBaseFDParams<TDBType>; end; implementation end. ---- The code provided above contains necessary units used by my main unit below (Model.Firedac.ConnectionParams), where the actual issue occurs. unit Model.Firedac.ConnectionParams; interface uses System.Classes, System.SysUtils, System.Generics.Collections, // Model.Firedac.ParamsTypes, Model.FiredacParams.BaseInterface, Model.DB.Exceptions; type iMSAccesseParams = iBaseFDParams<TMSAccessDriver>; iSQLiteParams = interface (iBaseFDParams<TSQLiteDriver>) function LockingMode(aValue: TSQLiteLockingMode): iBaseFDParams<TSQLiteDriver>; overload; function Encrypt(aValue: TSQLiteEncryptMode): iBaseFDParams<TSQLiteDriver>; overload; function LockingMode: TSQLiteLockingMode; overload; function Encrypt: TSQLiteEncryptMode; overload; end; iPostgreSqlParams = iBaseFDParams<TPostgreSqlDriver>; iMySQLParams = iBaseFDParams<TMySQLDriver>; iFirebirdParams = iBaseFDParams<TFirebirdDriver>; iInterbaseParams = iBaseFDParams<TInterbaseDriver>; iInterbaseLParams = iBaseFDParams<TInterbaseLiteDriver>; function GetDefault_SqliteParams(const aDatabase: string; const aUsername: string = ''; const aPassword: string = ''; const aLockingMode: TSQLiteLockingMode = mLockingExclusive; aEncrypt: TSQLiteEncryptMode = EncryptNone): iSQLiteParams; implementation type iBaseFiredacParams = iBaseFDParams<TBaseFiredacDriver>; TBaseConnectionParams = class(TInterfacedObject, iBaseFiredacParams) strict private protected function Pooled(aValue: Boolean): iBaseFiredacParams; overload; virtual; function Database(aValue: string): iBaseFiredacParams; overload; virtual; function Username(aValue: string): iBaseFiredacParams; overload; virtual; function Password(aValue: string): iBaseFiredacParams; overload; virtual; function Pooled: Boolean; overload; virtual; function Database: string; overload; virtual; function UserName: string; overload; virtual; function Password: string; overload; virtual; function Params: iBaseFiredacParams; virtual; procedure ValidateParams; virtual; abstract; end; TSqliteParams = class(TBaseConnectionParams, iSQLiteParams) public constructor Create (const aDatabase: string; const aUsername: string = ''; const aPassword: string = ''; const aLockingMode: TSQLiteLockingMode = mLockingExclusive; aEncrypt: TSQLiteEncryptMode = EncryptNone); procedure ValidateParams; override; function LockingMode(aValue: TSQLiteLockingMode): iBaseFDParams<TSQLiteDriver>; overload; virtual; function Encrypt(aValue: TSQLiteEncryptMode): iBaseFDParams<TSQLiteDriver>; overload; virtual; function LockingMode: TSQLiteLockingMode; overload; virtual; function Encrypt: TSQLiteEncryptMode; overload; virtual; end; function GetDefault_SqliteParams(const aDatabase: string; const aUsername: string = ''; const aPassword: string = ''; const aLockingMode: TSQLiteLockingMode = mLockingExclusive; aEncrypt: TSQLiteEncryptMode = EncryptNone): iSQLiteParams; begin Result := TSqliteParams.Create(aDatabase, aUsername,aPassword,aLockingMode, aEncrypt) as iSQLiteParams; end; end. TSqliteParams act as TTestFoo and TBaseConnectionParams as TBaseFoo- 14 replies
-
- code reuse
- class hierarchy
- (and 3 more)
-
inheritance Ensuring Consistent Base Interface Implementation in Delphi Class Hierarchy
bravesofts replied to bravesofts's topic in Algorithms, Data Structures and Class Design
I am looking for a good software design solution that helps me avoid repeatedly implementing methods from TBaseFoo. Logically, by adding iTestFoo as an ancestor to TTestFoo, I am always forced to implement the methods of iBaseFoo, which come from iTestFoo. I want to avoid re-implementation of these methods. I tried marking the methods of TBaseFoo as virtual, but it didn’t help.- 14 replies
-
- code reuse
- class hierarchy
- (and 3 more)
-
inheritance Ensuring Consistent Base Interface Implementation in Delphi Class Hierarchy
bravesofts replied to bravesofts's topic in Algorithms, Data Structures and Class Design
i search a workaround or a pure solution that let me avoid re-implementation of iBaseFoo methods since TBaseFoo Already there- 14 replies
-
- code reuse
- class hierarchy
- (and 3 more)
-
ifthen strange return value !
bravesofts posted a topic in Algorithms, Data Structures and Class Design
why this IfThen inline function gives me Object is Allocated in memory !! --- type TMainView = class(TForm) Label1: TLabel; procedure FormCreate(Sender: TObject); private { Private declarations } public { Public declarations } end; var MainView: TMainView; implementation type TMyClass = class private // fValue: string; class var ClassValue: string; function GetValue: string; procedure SetValue(const aValue: string); public property Value: string Read GetValue write SetValue; end; { TMyClass } function TMyClass.GetValue: string; begin Result := ClassValue; end; procedure TMyClass.SetValue(const aValue: string); begin ClassValue := aValue; end; { TMainView } function IsAllocated(aObj: TMyClass): Boolean; begin Result := Assigned(aObj); case Result of True: aObj.Value := 'the OBJECT Is Allocated ..'; False: aObj.Value := 'Not Allocated Yet !!'; end; end; procedure TMainView.FormCreate(Sender: TObject); var LObj: TMyClass; begin // LObj := nil; // LObj := TMyClass.Create; Label1.Caption := IfThen(IsAllocated(LObj), LObj.Value, LObj.Value); end; link to github test project here -
ifthen strange return value !
bravesofts replied to bravesofts's topic in Algorithms, Data Structures and Class Design
Did the tone of this conversation lean towards mockery or belittling the person asking the question, or am I mistaken? -- In any case, thank you for the information. -
ifthen strange return value !
bravesofts replied to bravesofts's topic in Algorithms, Data Structures and Class Design
i agree with you @Rollo62 on this term, we should be the first to ask a good questions to get a good answers with best accuracy of the truth .. By the way, the answer from ChatGPT above would have been impossible without the question being, in reality, the answer from the highly respected and dear-to-my-heart @Dalija Prasnikar. If you take a closer look at what ChatGPT provided above, you’ll notice that it did a wonderful job of summarize, re-format and complete ., and beautifully elaborating on the esteemed professor Dalija Prasnikar's response.. The above post from ChatGPT 4.o is the best proof of what you say. --- finally , I want to thank you all once again for your amazing and enthusiastic contributions. Your accuracy in providing information has really helped me understand and sum up a journey that many people might still be struggling with. -
ifthen strange return value !
bravesofts replied to bravesofts's topic in Algorithms, Data Structures and Class Design
i ask GPT for a good Example and gives me this: procedure TMainView.Btn_1Click(Sender: TObject); var LObj: TMyClass; // Declare a local variable of reference type begin // At this point, LObj is just a pointer, and it hasn't been assigned to any object yet. ShowMessage(IntToStr(Integer(LObj))); // This may show some random (garbage) value LObj := TMyClass.Create; // Now, LObj points to a new instance of TMyClass allocated on the heap. ShowMessage(IntToStr(Integer(LObj))); // This will show the actual memory address of the object instance // When you’re done, free the object to avoid memory leaks. LObj.Free; end; Explanation LObj Declaration: LObj is declared as a variable of type TMyClass. This is a reference type, which means LObj is just a pointer (an address) that will eventually point to an object instance. Memory Allocation: LObj itself is a local variable, so it is allocated on the stack. However, the object instance that LObj will point to is allocated on the heap when you create it using TMyClass.Create. Garbage Value: When LObj is declared, it hasn't been initialized to point to anything. The memory allocated on the stack for LObj might contain whatever data was there before, which is why ShowMessage(IntToStr(Integer(LObj))) might display a random (garbage) value. This is because stack memory isn't automatically cleared. Object Creation: When you create a new instance of TMyClass with LObj := TMyClass.Create;, the memory for this instance is allocated on the heap. LObj now holds the memory address of this instance. Managed Types: Only managed types (e.g., strings, dynamic arrays, interfaces) are automatically initialized to nil or equivalent values when declared. Since LObj is not a managed type, it can hold any value until you explicitly initialize it by creating an object. Key Takeaways Uninitialized Pointers: If you don't initialize a reference type variable (like LObj), it might contain a garbage value that points to an undefined memory location. Memory Allocation: Local variables are allocated on the stack, but the actual object instances they point to are allocated on the heap. Automatic Initialization: Only managed types are automatically initialized to nil or similar default values when declared. This example illustrates the importance of initializing your reference variables to nil or creating an object before using them to avoid unexpected behavior. ---- I have a much clearer understanding of the entire process now. Thank you, everyone! -
ifthen strange return value !
bravesofts replied to bravesofts's topic in Algorithms, Data Structures and Class Design
So, the heap might contain some garbage data, and when we declare a variable, the pointer may refer to something that isn’t related to our program at all. Does this happen only in Windows? -
ifthen strange return value !
bravesofts replied to bravesofts's topic in Algorithms, Data Structures and Class Design
Do random values only occur for local variables? Why does uninitialized memory sometimes contain garbage values, especially when an object hasn't been allocated yet? LObj is just a variable that will reference the object once TMyClass creates it. Does TMyClass automatically assign anything to LObj just by declaring it like this? var LObj: TMyClass; -
the Real Purpose of using Reintroduce
bravesofts posted a topic in Algorithms, Data Structures and Class Design
the Purpose of reintroduce is to make a second introduce for same method from base class (not marked as virtual or dynamic) with overload arguments in Drived Class whith inherited ofcourse .. reintroduce let us add inherited in implementation of that overload method that reintroduced in Derrived Class ex: type TBaseClass = class public constructor Create; // no virtual or dynamic end; TDerivedClass = class(TBaseClass) public // constructor Create; overload// introduced as overload but no arguments there !! constructor Create(aArg:T); reintroduce; overload; end; implementation { TBaseClass } constructor TBaseClass.Create; begin // for example No code here !! end; { TDerivedClass } constructor TDerivedClass.Create; begin inherited Create; // reintroduce let us make inherited here //since base method is not marked as virtual or dynamic .. MyCode; // our method here will implement both (the inherited + MyCode) // but since the inherited is empty : the reintroduce here is Totally useless !! // the aim of reintroduce is to let us Merge the old method from base to reintroduce it // as a new method in derived class using directive [inherited] // does the overload necessary ? // if there is no necessary to add new arguments you can add just reintroduce to use // the inherited directive there .. // Is inherited mandatory when using reintroduce ? // a reintroduce without inherited is totally nosense !! end; finally : reintroduce is used especially for two Reasons: make inherited + overload with new parameters for same base method in Drived class make just inherited without overload it with new parameters Q1)does reintroduce work also with base methods marked as virtual or dynamic ? A1) do you heard about override ? Q2) but if i need to introduce it with my custom parameters ? A2) if that case ofcourse you need reintroduce; with overload; Q3) is overload mandatory ? A3) since reintroduce her second work is to hide any warnning compiler i can say yes the overload is a mandatory logically .. ----- if i'm wrong plz tell me (Many thanks in Advance) -
unit API.Generics; interface uses System.Classes // , System.Generics.Collections , System.Generics.Defaults ; type TSort = (sNone, sAsc, sDes); TDynamicObjectList<T: class> = class(TObjectList<T>) private fComparer: TComparison<T>; fSortField: string; fSort: TSort; function CompareNumbers(const L, R: Integer): Integer; function CompareObjects(const aLeft, aRight: T): Integer; public constructor CreateWithSort(const aSortField: string; aSort: TSort = sAsc); procedure Sort(aSort: TSort = sAsc); function IsSortedCorrectly: Boolean; end; implementation uses System.SysUtils , System.Rtti , System.TypInfo ; { TDynamicObjectList<T> } constructor TDynamicObjectList<T>.CreateWithSort(const aSortField: string; aSort: TSort); begin inherited Create(True); fSortField := aSortField; fSort := aSort; fComparer := CompareObjects; end; function TDynamicObjectList<T>.CompareNumbers(const L, R: Integer): Integer; begin Result := L - R; end; function TDynamicObjectList<T>.CompareObjects(const aLeft, aRight: T): Integer; var L_Ctx : TRttiContext; L_Typ : TRttiType; L_Prop : TRttiProperty; L_Left : TClass absolute aLeft; L_Right : TClass absolute aRight; L_LeftValue, L_RightValue: TValue; begin if fSortField = '' then begin // Use default comparer if no specific field is specified .. Result := TComparer<T>.Default.Compare(T(L_Left), T(L_Right)); Exit; end; L_Ctx := TRttiContext.Create; try L_Typ := L_Ctx.GetType(T); // Get RTTI for type ( T ) L_Prop := nil; L_Prop := L_Typ.GetProperty(fSortField); if Assigned(L_Prop) then begin L_LeftValue := L_Prop.GetValue(L_Left); L_RightValue := L_Prop.GetValue(L_Right); case L_LeftValue.Kind of tkInteger, tkInt64: case fSort of sAsc: Result := CompareNumbers(L_LeftValue.AsInteger, L_RightValue.AsInteger); sDes: Result := CompareNumbers(L_RightValue.AsInteger, L_LeftValue.AsInteger); else Result := TComparer<T>.Default.Compare(T(L_Left), T(L_Right)); end; tkString, tkWString, tkLString, tkUString: case fSort of sAsc: Result := CompareNumbers(Integer.Parse(L_LeftValue.AsString), Integer.Parse(L_RightValue.AsString)); sDes: Result := CompareNumbers(Integer.Parse(L_LeftValue.AsString), Integer.Parse(L_RightValue.AsString)); else Result := TComparer<T>.Default.Compare(T(L_Left), T(L_Right)); end; else TComparer<T>.Default.Compare(T(L_Left), T(L_Right)); end; end else Result := 0; // Handle case where property is not found finally L_Ctx.Free; end; end; function TDynamicObjectList<T>.IsSortedCorrectly: Boolean; var I: Integer; begin Result := True; for I := 1 to Count - 1 do begin if CompareObjects(Items[I - 1], Items[I]) > 0 then begin Result := False; Break; end; end; end; procedure TDynamicObjectList<T>.Sort(aSort: TSort); begin fSort := aSort; inherited Sort(TComparer<T>.Construct(fComparer)); end; end. using: in separate Unit: MyFonts.pas type TFonType = (ft_TTF, ft_OTF, ft_Unknown); TFontInfo = class strict private fFileID, fFontName : string; fFontType : TFonType; fFontFileName: string; private function Get_FontType: string; procedure Set_FontType(const aValue: string); public constructor Add(const aFileID, aFontName: string; const aFontType: TFonType); destructor Destroy; override; property ID: string read fFileID write fFileID; property FontName:string read fFontName write fFontName; property FontType:string read Get_FontType write Set_FontType; property FontFileName: string read fFontFileName write fFontFileName; end; TFontsList = class(TDynamicObjectList<TFontInfo>); in MainForm: uses MyFonts; procedure TMainView.FormCreate(Sender: TObject); var L_FontInfo: TFontInfo; L_ListItem: TListItem; begin fFontsRes_List := TFontsList.CreateWithSort('ID'); // Add some sample data fFontsLst.Add(TFontInfo.Add('3', 'Courier New', ft_TTF)); fFontsLst.Add(TFontInfo.Add('1', 'Arial', ft_TTF)); fFontsLst.Add(TFontInfo.Add('2', 'Times New Roman', ft_OTF)); // Sort the list by ID in Asc fFontsLst.Sort(sAsc); // Populate the ListView for L_FontInfo in fFontsLst do begin L_ListItem := LV_Fonts.Items.Add; L_ListItem.Caption := L_FontInfo.ID; L_ListItem.SubItems.Add(L_FontInfo.FontName); L_ListItem.SubItems.Add(L_FontInfo.FontType); L_ListItem.SubItems.Add(L_FontInfo.FontFileName); end; end; procedure TMainView.FormDestroy(Sender: TObject); begin fFontsRes_List.Free; end; currentlly it's works only with fields marked as string or integer but real value are in integer and sorted using : CompareNumbers
-
the Real Purpose of using Reintroduce
bravesofts replied to bravesofts's topic in Algorithms, Data Structures and Class Design
ok , I totally agree with that definition in dokwiki.. but here: https://stackoverflow.com/questions/53806/reintroducing-functions-in-delphi plese someone tell me Why all this confusion in link above, about something that was created specifically just for that senarion in dokwiki? atleast everyone there has a logic reason for that.. Please, I need to turn this page permanently... Jim McKeeth said: If you declare a method in a descendant class that has the same name as a method in an ancestor class then you are hiding that ancestor method — meaning if you have an instance of that descendant class (that is referenced as that class) then you will not get the behavior of the ancestor. When the ancestor's method is virtual or dynamic, the compiler will give you a warning. Now you have one of two choices to suppress that warning message: Adding the keyword reintroduce just tells the compiler you know you are hiding that method and it suppresses the warning. You can still use the inherited keyword within your implementation of that descended method to call the ancestor method. If the ancestor's method was virtual or dynamic then you can use override. It has the added behavior that if this descendant object is accessed through an expression of the ancestor type, then the call to that method will still be to the descendant method (which then may optionally call the ancestor through inherited). So difference between override and reintroduce is in polymorphism. With reintroduce, if you cast the descendant object as the parent type, then call that method you will get the ancestor method, but if you access it the descendant type then you will get the behavior of the descendant. With override you always get the descendant. If the ancestor method was neither virtual nor dynamic, then reintroduce does not apply because that behavior is implicit. (Actually you could use a class helper, but we won't go there now.) In spite of what Malach said, you can still call inherited in a reintroduced method, even if the parent was neither virtual nor dynamic. Essentially reintroduce is just like override, but it works with non-dynamic and non-virtual methods, and it does not replace the behavior if the object instance is accessed via an expression of the ancestor type. Further Explanation: Reintroduce is a way of communicating intent to the compiler that you did not make an error. We override a method in an ancestor with the override keyword, but it requires that the ancestor method be virtual or dynamic, and that you want the behavior to change when the object is accessed as the ancestor class. Now enter reintroduce. It lets you tell the compiler that you did not accidentally create a method with the same name as a virtual or dynamic ancestor method (which would be annoying if the compiler didn't warn you about). is there a deep example where introducing each case with strong reason individually ? It’s essential for my overall well-being to close this chapter once and for all... -
I'm confused...why didn't the Embarcadero take this seriously? Why does every Delphi developer have to install more than one version of Delphi to be able to support almost Android phones? On the other hand we find Android Studio, for example, with only one version of that IDE that still covers all Android phones, starting from android 5 up to the current latest version.!! is there a workaround solution that help to make Delphi 12 support even old Android phones? i mean (a real support not fake..) is there a complete SDK solution where users under delphi12 could support old phones starting from Android 5 to the latest current version ? thank you All
-
making Delphi 12 support even old Android phones?
bravesofts replied to bravesofts's topic in Delphi IDE and APIs
wow thank you @Dave Nottage that solution from [Delphi World] is working as a charm ! -
delphi Thread ITask.ExecuteWork not wait until Task finish in mobile devices?
bravesofts posted a topic in Cross-platform
i have this code here: fTask: ITask; fTask := TTask.Create( procedure begin while not True do Application.ProcessMessages; TThread.Synchronize(TThread.Current, procedure begin // update ui end); end); fTask.ExecuteWork; // this will stop here.. until [fTask] finish work !! In android didn't wait untill Task Complete !!- 24 replies
-
- android
- multithreading
-
(and 2 more)
Tagged with:
-
delphi Thread ITask.ExecuteWork not wait until Task finish in mobile devices?
bravesofts replied to bravesofts's topic in Cross-platform
sorry @Remy Lebeau no i didn't at that way !! --- i ask both question at the same time !! --- and with Your big and huge respect of your knowledge, I'm done learning that Method: [ITask.ExecuteWork] from ITask is: runs the task in the calling thread ... ---- again please: Forgive my ignorance and stupidity !! i was just there to ask and not because this site or other didn't help !! --- finally . i thank you all for your replys and especially for taking from your time.. i love you all & respect you all .. @Dalija Prasnikar regardless of others... i respect you a lot .- 24 replies
-
- android
- multithreading
-
(and 2 more)
Tagged with:
-
delphi Thread ITask.ExecuteWork not wait until Task finish in mobile devices?
bravesofts replied to bravesofts's topic in Cross-platform
also i learn that the Method ExecuteWork: [ is used to run the task in the calling thread => in my case the main App thread ] like inject or run a safe thread inside the MainThreadAPP and this exactly what i looking for.... --- so my question here: Why Method ExecuteWork Fail in mobile device (especially ANDROID) ? ----- is this have problem with Android OS ?? ----- Please don't tell me that Method : ExecuteWork is not a regular or illegal or what ever else ... otherwhise why the EMB Group add it inside the interface ITASK ? ---- what i know in language programming : the interface is safer and destinated at-least to users like me .... --- with best Respects & Regards ...- 24 replies
-
- android
- multithreading
-
(and 2 more)
Tagged with:
-
delphi Thread ITask.ExecuteWork not wait until Task finish in mobile devices?
bravesofts replied to bravesofts's topic in Cross-platform
sorry again ... --- last question: is it impossible to create threads in mobile devices while avoiding the main app thread from going to the next line of code until tasks complete ? for example this code here didn't work in android devices: begin _Taskcomplete := false; try fTask := TTask.Create( procedure begin // Here you do your task code while not _Taskcomplete do Lbl_Task.Text := ElapsedSec.ToString; TThread.Synchronize(nil, procedure begin // Here you can call code that needs to run after task is finished Lbl_Task.Text := 'task complete ..'; end); end); fTask.Start; finally while not _Taskcomplete do Application.ProcessMessage; // in Android the APP freeze !! showMessage('we wait until Task Complete to show you this message !!'); end; end; from what i learn above is i can only use wait function to run the SoCalled "After Task Complete Procedures or functions" inside the task thread using synchronize method..!!- 24 replies
-
- android
- multithreading
-
(and 2 more)
Tagged with:
-
delphi Thread ITask.ExecuteWork not wait until Task finish in mobile devices?
bravesofts replied to bravesofts's topic in Cross-platform
Not block the main thread in that definition... !!! I think the stupid sleep function is the unsafe way to block main thread... ---- I mean block main thread using the safe way like executeWork does... ---- I'm afread again : Delphi does not support background threads in Android and iOS devices where the main thread wait smoothly and safe...- 24 replies
-
- android
- multithreading
-
(and 2 more)
Tagged with: