// in your classes, you decive where define it.... in according with your necessity!!! // private // protected // public // published // // xxxxx = class( 1 class, 1 interface, 2 interface, 3 interface, etc... etc... etc... ) // // TIntefacedObject is a default when using this definition, but exists many other options... // TMyClass_ONE_UsingInterface = class(TInterfacedObject, IMyInterf_BASE_ONE) // protected // all sub-classes (inheriting...) can use it FMyValue: string; // // example using: Private and Public sections!!! you decide in your class definition!!! // private // property function GetHelloWorld_ONE: string; procedure SetHelloWorld_ONE(Value: string);
public // procedures or functions procedure prcHelloWorld_ONE; function fncHelloWorld_ONE: integer; // // property property propHelloWorld_ONE: string read GetHelloWorld_ONE write SetHelloWorld_ONE; end;
// here, Class_TWO is inheriing all defitions from Class_ONE, including the interface defintions (Interf_ONE) + Interf_TWO
TMyClass_TWO_Using_Inheriting_Other_Interface = class(TMyClass_ONE_UsingInterface, IMyInterf_BASE_TWO) public // from "IMyInterf_BASE_TWO" procedure prcHelloWorld_TWO; end;
implementation
{ TMyClass_ONE_UsingInterface }
function TMyClass_ONE_UsingInterface.fncHelloWorld_ONE: integer; begin result := 123; end;
function TMyClass_ONE_UsingInterface.GetHelloWorld_ONE: string; begin result := 'hello'; end;
procedure TMyClass_ONE_UsingInterface.prcHelloWorld_ONE; begin // ??? end;
procedure TMyClass_ONE_UsingInterface.SetHelloWorld_ONE(Value: string); begin if (Value = 'Hello') then Value := 'World' else FMyValue := 'WOW China'; // <--- end;
{ TMyClass_TWO_Using_Inheriting_Other_Interface }
procedure TMyClass_TWO_Using_Inheriting_Other_Interface.prcHelloWorld_TWO; begin // "FMyValue" is a "Protected" field on "TMyClass_ONE_UsingInterface", then, it can be accessed on this sub-class (inherited from...) if FMyValue = 'World' then // <--- FMyValue := 'Hello'; end;
end.
----------------------------------------------
The higher the degree, the greater the respect given to the humblest!RAD 11.3
type TForm1 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end;
var Form1: TForm1;
implementation
{$R *.dfm}
uses uMyClasses_Interfaces;
var // using the "class" MyObj_As_Class_ONE: TMyClass_ONE_UsingInterface; MyObj_As_Class_TWO: TMyClass_TWO_Using_Inheriting_Other_Interface; // // using the "interface" MyObj_As_Interf_ONE: IMyInterf_BASE_ONE; MyObj_As_Interf_TWO: IMyInterf_BASE_TWO; // LValue: integer; LText : string;
The use of "Interfaces" allows you to show only what is "strictly necessary" for the user (programmer) of your interfaces!!!
In this way, the new programmer will only know what really matters to his project!!! It is not important to show the "real code" (what was actually abstracted), so you protect your API (or code) so that it is not used improperly or wrongly, avoiding many programming errors (bugs).
That's how the big platforms like Alibaba, Google, Amazon, Microsoft, etc... do it!!!
In the past, it was very common to see a lot of "DLLs" scattered around the system... today, there was a lot of talk about "API"...
in the end, it's practically the same thing, that is: --- all the actual software code was abstracted for more comfortable use by new programmers. Thus, many basic programming errors are avoided!!!
However, an "Interface" is not the solution for everything!!! It is often necessary to use the "Class"!!! So, everything in its place!!!
----------------------------------------------
The higher the degree, the greater the respect given to the humblest!RAD 11.3
1) The performance should be the same as using "TClassXXXX",.... an "Interface" is just a way to hide the part of the class that you don't want to share with other users (programmers). Just it!!! If performance is lost, then the class is poorly designed!
2)When you use "CTRL+mouse-click" on an object that uses "Interface", the IDE finds the definition of the interface, and, it's correct!!! Well, you are defining that the interface is the only means that the user (Programmer) has to execute the real code of the class! So the "Code-Editor" only knows the "interface", not the class directly!!! == "Interface" = "Hiding real code"
----------------------------------------------
The higher the degree, the greater the respect given to the humblest!RAD 11.3
3. 对象缓冲:基于接口的内存管理,稍微做点修改,你就可以使用把接口存起来的方式,实现自动的对象缓冲。原本接口引用计数为零的时候,对象自动释放,修改为引用计数为零时,对象自动回到缓冲池。使用非常少的代码就能实现这个功能。如果一个对象需要频繁创建和释放,比如1秒钟有几十上百次,你不做缓冲,直接创建和释放,就会发现 CPU 会忙得不得了。而使用对象缓冲,CPU 马上就不忙了。
继承的价值主要在于:解决代码的复用性和可维护性 接口的价值主要在于:设计、设计好各种规范(方法),让其他类去实现这些方法 接口比继承更加灵活 继承是满足is - a 的关系,而接口只需满足like-a关系
接口简单的理解可认为是一个抽象类,我们先定义一个抽象类和接口来对比之间的异同,代码如下:
type IFormattedNumber = interface //定义接口 function FormattedString: string; end;
TFormattedNumber = class //定义抽象类 public function FormattedString: string; virtual; abstract; end; 上面定义了一个接口IFormattedNumber和抽象类TFormattedNumber,从delphi方法上来说,都不能直接实例化,接口是通过类来实现的,而抽象类则是通过其派生类来实现其具体的功能。抽象类与接口的不同我理解有以下几点:
type IFormattedNumber2 = Interface(IFormattedNumber) procedure SetValue(AValue); end;
二、接口的声明和实现 接口声明和实现很简单,请看下面代码:
unit Unit2;
interface
uses SysUtils;
type IFormattedNumber = interface //接口声明 ['{F9E8F5DE-781B-4B5B-B78A-0F88CF50E53F}'] {GUID,Alt+Shift+G快捷键生成} function FormattedInteger: string; end; TFormattedNumber=class(TObject,IFormattedNumber) //实现接口类 private FValue:Integer; public constructor Create(AValue:Integer); destructor destroy;override; function FormattedInteger: string; //实现接口函数FormattedInteger; end;
implementation constructor TFormattedNumber.Create(AValue:Integer); begin inherited Create; FValue:=AValue; end; destructor TFormattedNumber.destroy; begin inherited destroy; end; function TFormattedNumber.FormattedInteger:string; begin Result:=IntToStr(FValue); end;