任何一门语言,只要具备了"封装,继承,多态"这三项基本能力,不管其实现方式是直接或曲折、复杂或简洁,就可以称之为“面向对象”的语言。
Delphi当年的迅速走红,是以其RAD快速开发吸引程序员的目光。这无疑是它最吸引人的优势,但同时也让人误以为delphi只是vb的高级版本,从而忽视了其面向对象的特性。
其实Pacscal发展到Delphi,已经完全具备了面向对象的所有特点:允许自定义类,类可以继承(单继承),允许方法重载/覆写,可以定义接口,类可以实现接口,允许定义静态方法(即class方法),虚方法,抽象类...等等,对于delphi怀有偏见的朋友,你还会怀疑delphi的面向对象能力吗?
下面是一些演示代码:
1.先定义一个基类TPeople
代码
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
代码
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
代码
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接口
代码
unit
UICook;
interface
type
ICook = interface // 定义一个接口
procedure Cook; // 接口的方法定义
end ;
implementation
end .
interface
type
ICook = interface // 定义一个接口
procedure Cook; // 接口的方法定义
end ;
implementation
end .
5.放到ConsoleApplication中测试一把:
代码
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接口,所以我会做饭:)