重温Delphi之:面向对象
任何一门语言,只要具备了"封装,继承,多态"这三项基本能力,不管其实现方式是直接或曲折、复杂或简洁,就可以称之为“面向对象”的语言。
Delphi当年的迅速走红,是以其RAD快速开发吸引程序员的目光。这无疑是它最吸引人的优势,但同时也让人误以为delphi只是vb的高级版本,从而忽视了其面向对象的特性。
其实Pacscal发展到Delphi,已经完全具备了面向对象的所有特点:允许自定义类,类可以继承(单继承),允许方法重载/覆写,可以定义接口,类可以实现接口,允许定义静态方法(即class方法),虚方法,抽象类...等等,对于delphi怀有偏见的朋友,你还会怀疑delphi的面向对象能力吗?
下面是一些演示代码:
1.先定义一个基类TPeople
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
unit UPeople;
interface
type
TPeople = class(TObject)
private
_name:string; //私成成员定义
procedure Set_Name(value:string);//Name属性的set方法定义
function Get_Name:string; //Name属性的get方法定义
protected
function Get_Sex:Boolean;virtual;abstract; //定义抽象虚方法,由子类去实现
public
property Name:string read Get_Name write Set_Name; //定义Name属性
property Sex:Boolean read Get_Sex; //定义Sex只读属性(该属性并未实现,而是交由子类去实现)
class function ToString:string; //类方法,有点象c#中的static静态方法
procedure ShowName;//公用实例方法
end;
//实现部分
implementation
procedure TPeople.Set_Name(value:string);
begin
_name := value;
end;
function TPeople.Get_Name:string;
begin
result := _name;
end;
class function TPeople.ToString:string;
begin
result := 'This is a People Class';
end;
procedure TPeople.ShowName;
begin
Writeln('姓名:' + _name);
end;
end.
interface
type
TPeople = class(TObject)
private
_name:string; //私成成员定义
procedure Set_Name(value:string);//Name属性的set方法定义
function Get_Name:string; //Name属性的get方法定义
protected
function Get_Sex:Boolean;virtual;abstract; //定义抽象虚方法,由子类去实现
public
property Name:string read Get_Name write Set_Name; //定义Name属性
property Sex:Boolean read Get_Sex; //定义Sex只读属性(该属性并未实现,而是交由子类去实现)
class function ToString:string; //类方法,有点象c#中的static静态方法
procedure ShowName;//公用实例方法
end;
//实现部分
implementation
procedure TPeople.Set_Name(value:string);
begin
_name := value;
end;
function TPeople.Get_Name:string;
begin
result := _name;
end;
class function TPeople.ToString:string;
begin
result := 'This is a People Class';
end;
procedure TPeople.ShowName;
begin
Writeln('姓名:' + _name);
end;
end.
2.再定义一个子类TMan
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
unit UMan;
interface
uses
UPeople ;
type
TMan = class(TPeople)
constructor Create(name:string); overload ; //重载构造函数
private
_sex:Boolean;
protected
function Get_Sex:Boolean; override;
public
function ToString:string; //实例方法
end;
implementation
constructor TMan.Create(name:string); //注意写法:实现的时候不用加overload关键字
begin
inherited Create;
_sex := true; //男性强制定义为true
Self.Name := name;
end;
function TMan.Get_Sex:Boolean;
begin
result := _sex;
end;
function TMan.ToString:string;
begin
result := '这是TMan中的ToString方法';
end;
end.
interface
uses
UPeople ;
type
TMan = class(TPeople)
constructor Create(name:string); overload ; //重载构造函数
private
_sex:Boolean;
protected
function Get_Sex:Boolean; override;
public
function ToString:string; //实例方法
end;
implementation
constructor TMan.Create(name:string); //注意写法:实现的时候不用加overload关键字
begin
inherited Create;
_sex := true; //男性强制定义为true
Self.Name := name;
end;
function TMan.Get_Sex:Boolean;
begin
result := _sex;
end;
function TMan.ToString:string;
begin
result := '这是TMan中的ToString方法';
end;
end.
3.再来一个子类TWoman
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
unit UWoman;
interface
uses
UPeople,UICook;
type
TWoman = class(TPeople,ICook)
constructor Create(name:string); overload ;
private
_sex:Boolean;
protected
function Get_Sex:Boolean; override;
public
procedure Cook;//接口的方法实现定义
procedure ShowName;overload;
//如果Class是从TObject继承的,又想实现接口的话,必须实现下面这三个function,
//如果想偷懒的话,把UPeople改成从TInterfacedObject继承就可以省掉这个步骤了
function _AddRef:Integer; stdcall;
function _Release:Integer;stdcall;
function QueryInterface(const IID:TGUID;out Obj):HResult; stdcall;
end;
implementation
function TWoman._AddRef:Integer;
begin
result :=-1;
end;
function TWoman._Release:Integer;
begin
result :=-1;
end;
function TWoman.QueryInterface(const IID:TGUID;out Obj):HResult;
const
E_NOINTERFACE = $80004002;
begin
if GetInterface(IID,Obj) then
Result := 0
else
Result := -1; {E_NOINTERFACE}
end;
constructor TWoman.Create(name:string);
begin
inherited Create;
_sex := false;
Self.Name := name;
end;
function TWoman.Get_Sex:Boolean;
begin
result := _sex;
end;
procedure TWoman.ShowName;
begin
Writeln('女人总是喜欢搞点花样,所以重载一下哈.')
end;
procedure TWoman.Cook;
begin
Writeln('因为我实现了ICook接口,所以我会做饭:)')
end;
end.
interface
uses
UPeople,UICook;
type
TWoman = class(TPeople,ICook)
constructor Create(name:string); overload ;
private
_sex:Boolean;
protected
function Get_Sex:Boolean; override;
public
procedure Cook;//接口的方法实现定义
procedure ShowName;overload;
//如果Class是从TObject继承的,又想实现接口的话,必须实现下面这三个function,
//如果想偷懒的话,把UPeople改成从TInterfacedObject继承就可以省掉这个步骤了
function _AddRef:Integer; stdcall;
function _Release:Integer;stdcall;
function QueryInterface(const IID:TGUID;out Obj):HResult; stdcall;
end;
implementation
function TWoman._AddRef:Integer;
begin
result :=-1;
end;
function TWoman._Release:Integer;
begin
result :=-1;
end;
function TWoman.QueryInterface(const IID:TGUID;out Obj):HResult;
const
E_NOINTERFACE = $80004002;
begin
if GetInterface(IID,Obj) then
Result := 0
else
Result := -1; {E_NOINTERFACE}
end;
constructor TWoman.Create(name:string);
begin
inherited Create;
_sex := false;
Self.Name := name;
end;
function TWoman.Get_Sex:Boolean;
begin
result := _sex;
end;
procedure TWoman.ShowName;
begin
Writeln('女人总是喜欢搞点花样,所以重载一下哈.')
end;
procedure TWoman.Cook;
begin
Writeln('因为我实现了ICook接口,所以我会做饭:)')
end;
end.
注意,TWoman这个子类实现了接口ICook,其定义如下:
4.ICook接口
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
unit UICook;
interface
type
ICook = interface //定义一个接口
procedure Cook;//接口的方法定义
end;
implementation
end.
interface
type
ICook = interface //定义一个接口
procedure Cook;//接口的方法定义
end;
implementation
end.
5.放到ConsoleApplication中测试一把:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
program ClassDemo;
{$APPTYPE CONSOLE}
uses
SysUtils,
UPeople in 'UPeople.pas',
UMan in 'UMan.pas',
UWoman in 'UWoman.pas',
UICook in 'UICook.pas';
var
aPeople:TPeople;
aMan:TMan;
aWoman:TWoman;
aCook:ICook;
begin
aPeople := TPeople.Create;
aPeople.Name := 'jimmy.yang';
Writeln(aPeople.Name);
Writeln(TPeople.ToString);//调用静态方法
aPeople.ShowName;
Writeln('----------------------------------------');
aMan := TMan.Create('杨俊明');
Writeln(aMan.Name);
Writeln(aMan.Sex);
aMan.ShowName; //通过继承得来的方法
Writeln(aMan.ToString);//TMan实例中的对象方法
Writeln('----------------------------------------');
aWoman := TWoman.Create('小龙女');
Writeln(aWoman.Name);
Writeln(aWoman.Sex);
aWoman.ShowName; //调用重载后的方法
aWoman.Cook;//实现接口得来的方法
Writeln('----------------------------------------');
aCook := ICook(aWoman);//类还可以转化为接口
aPeople.Free;
aPeople:= TWoman.Create('翠花'); //同样也允许子类创建得到父类
aPeople.ShowName;
aWoman.Free;
aWoman := TWoman(aPeople);
aWoman.Cook;
Readln;
end.
{$APPTYPE CONSOLE}
uses
SysUtils,
UPeople in 'UPeople.pas',
UMan in 'UMan.pas',
UWoman in 'UWoman.pas',
UICook in 'UICook.pas';
var
aPeople:TPeople;
aMan:TMan;
aWoman:TWoman;
aCook:ICook;
begin
aPeople := TPeople.Create;
aPeople.Name := 'jimmy.yang';
Writeln(aPeople.Name);
Writeln(TPeople.ToString);//调用静态方法
aPeople.ShowName;
Writeln('----------------------------------------');
aMan := TMan.Create('杨俊明');
Writeln(aMan.Name);
Writeln(aMan.Sex);
aMan.ShowName; //通过继承得来的方法
Writeln(aMan.ToString);//TMan实例中的对象方法
Writeln('----------------------------------------');
aWoman := TWoman.Create('小龙女');
Writeln(aWoman.Name);
Writeln(aWoman.Sex);
aWoman.ShowName; //调用重载后的方法
aWoman.Cook;//实现接口得来的方法
Writeln('----------------------------------------');
aCook := ICook(aWoman);//类还可以转化为接口
aPeople.Free;
aPeople:= TWoman.Create('翠花'); //同样也允许子类创建得到父类
aPeople.ShowName;
aWoman.Free;
aWoman := TWoman(aPeople);
aWoman.Cook;
Readln;
end.
运行结果:
jimmy.yang
This is a People Class
姓名:jimmy.yang
----------------------------------------
杨俊明
TRUE
姓名:杨俊明
这是TMan中的ToString方法
----------------------------------------
小龙女
FALSE
女人总是喜欢搞点花样,所以重载一下哈.
因为我实现了ICook接口,所以我会做饭:)
----------------------------------------
姓名:翠花
因为我实现了ICook接口,所以我会做饭:)
作者:菩提树下的杨过
出处:http://yjmyzz.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
出处:http://yjmyzz.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。