在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
作者:巴哈姆特 function func(): Boolean; function func(const x: Char): Boolean;
这样是会出语法错误的,原因是因为标识符规则限制。但是问题出来了,如果我们需要几个功能相似但是参数不同的函数,那么根据标识符规则,我们就必须定义几个不同名,但是功能相同或相似的函数。 function SubInt(const Value1, Value2: Integer): Integer; functino SubReal(const Value1, Value2: Real): Real; function SubDouble(const Value1, Value2: Double): Double; implementation function SubInt(const Value1, Value2: Integer): Integer; begin Result:= Value1 - Value2; end; functino SubReal(const Value1, Value2: Real): Real; begin Result:= Value1 - Value2; end; function SubDouble(const Value1, Value2: Double): Double; begin Result:= Value1 - Value2; end;
我们可以看到,这三个函数除了参数名不同外,实现部分是一样的,这为程序的一致性带来了一定的麻烦。如果能定义一个同名函数来处理这几种不同情况的话,便有利于代码的重用,也有利于我们的记忆。这时我们就可以用overload来完成我们的需求了。 function Sub(const Value1, Value2: Integer): Integer; overload; function Sub(const Value1, Value2: Real): Real; overload; function Sub(const Value1, Value2: Double): Double; overload; implementation function Sub(const Value1, Value2: Integer): Integer; begin Result:= Value1 - Value2; end; function Sub(const Value1, Value2: Real): Real; begin Result:= Value1 - Value2; end; function Sub(const Value1, Value2: Double): Double; begin Result:= Value1 - Value2; end;
由此可见,名字相同而参数的数据类型或数量不同的函数,称之为overload函数。这是因为编译器在编译时不仅使用了函数名的信息,还使用了参数类型和数量的信息,通过组合这些信息可以确定分配地址时需要的唯一标识,通常我们叫他signature。例如: Sub(1, 2); // 调用的是 function Sub(const Value1, Value2: Integer): Integer; Sub(1.0, 2.0); // 调用的是 function Sub(const Value1, Value2: Real): Real;
这里要说明一下,如果是同名函数,并且参数也相同,只是返回值不同的话,是不能实现overload的。 对于overload的说明就到这里吧,下面我们来说override: 部分的类成员或方法都已经包含在新类中。 type TBaseClass = class(TObject) // 定义一个新的父类 protected FMessage: string; public constructor Create(); // 构造方法 procedure MessageBox(); virtual; // 显示字符串 end; TChildClass = class(TBaseClass) // 定义一个TBaseClass的派生类 public procedure MessageBox(); override; // 重载父类中的方法 end; implementation constructor TBaseClass.Create; begin inherited Create(); // 继承父类中的构造方法Create FMessage:= ClassName; // 初始化信息字符串为类名 end; procedure TBaseClass.MessageBox; begin ShowMessage(FMessage); // 显示字符串 end; procedure TChildClass.MessageBox; begin FMessage:= FMessage + FMessage; inherited MessageBox(); // 继承父类中原有MessageBox方法的原有功能 end;
好,我们可以编写一个简单的例子来调用一下: var Child: TChildClass; begin Child:= TChildClass.Create; Child.MessageBox(); Child.Free; end;
代码执行后,应该可以看到一个弹出“TChildClassTChildClass”字符串的对话框。 var Child: TBaseClass; begin Child:= TChildClass.Create; Child.MessageBox(); Child.Free; end;
执行这段测试代码和我们上面的代码是一样的效果的。然后我们再把TBaseClass类的方法MessageBox后的virtual关键字和子类中的override关键字去掉,再执行一次看看,应该是看到一个弹出“TChildClass”字符串的对话框。 virtual和dynamic方法 Delphi的编译器会自动维护用于添加虚方法的虚方法表(VMT)和用于添加动态方法的动态方法表(DMT)。 总的来说,虚方法侧重于提高速度,动态方法侧重于节省内存,如果某方法其后代类基本都需要override的,那么推荐使用virtual,如果某方法不经常或者几乎不在后代类中被override的,则推荐使用dynamic。 abstract方法 类方法 type TNewClass = class(TObject) public class procedure AClassFunciton(...): ...; end;
鸣谢刘啸,没有刘啸的查错,文章将会难看很多,哈哈^_^ |
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论