请注意 ...... 著作权所有人:物泽计算机事业股份有限公司、 MISOO对象技术顾问团队、对象导向杂志作者、等。 u本文件摘自 对象导向杂志、精通对象观念与技术等书籍著作。 u本文件仅供您的参阅,请遵守著作权法,不得做其它商业用途。
主题: 程序多重定义(Overloading)
?????? 内容 ?????? v 1. 程序成员的多重定义
1. 程序成员的多重定义
「程序多重定义」(Function Overloading)又称为「程序重复定义」。它让对象更具弹性﹐能处理多样化之讯息。这观念源于日常生活经验。例如﹐我们常说﹕ ◎ 猫 玩 绣球 ◎ 猫 玩 老鼠 ◎ 猫 玩 鱼
猫玩绣球与玩老鼠之玩法不尽相同。但何以使用同一动词──「玩」呢﹖也许人们认为其目的是一致的﹕猫获得快乐。上述的「猫」为类别﹐而某只猫是对象。例如﹕加菲猫是对象﹐它可接受讯息──
其中﹐「玩」代表着动作和过程﹐而绣球、老鼠及鱼则是「玩」之对象。回想﹐在程序中﹐「程序」代表一项动作及过程﹐而「自变量值」则为程序之处理对象。因之﹐上图可表示为── 图1、 play()之多重定义
OOP 程序设计之理想为﹕让程序之写法与人们日常生活经验吻合﹐于是设计个Play()程序﹐让它能接受不同型态之资料做为处理对象。上述Play()已具「多重定义」﹐其特点是── 1. 程序名称相同﹐例如﹕Play()。 2. 自变量不同﹐例如﹕老鼠和鱼。
因猫玩绣球和玩老鼠的方法略有不同﹐例如老鼠是活的而绣球是死的﹐其玩的过程亦不尽相同。为了表示动作与过程之不同﹐Play()程序内之指令也有所不同。例如﹕
写VB程序时﹐其格式必须是──
Class Cat Public Overloads Sub Play(绣球) 指令 ....... End Sub Public Overloads Sub Play(老鼠) 指令 ....... End Sub Public Overloads Sub Play(鱼) 指令 ....... End Sub End Class
这就是「程序成员多重定义」了。Cat 类别含有三种Play()之定义﹐其自变量不同而且内部指令亦不相同。于是Play()程序能接受不同之自变量﹐并执行不同之指令﹐使得Play()具弹性了。请看个程序──
'ex01.bas Imports System.ComponentModel Imports System.Drawing Imports System.WinForms '------------------------------------------------------- Class Example Public Overloads Sub Display() MessageBox.Show("****") End Sub Public Overloads Sub Display(ByVal r As Integer) MessageBox.Show(str(r)) End Sub Public Overloads Sub Display(ByVal f As Double) MessageBox.Show(str(f + 2)) End Sub Public Overloads Sub Display(ByVal s As String) MessageBox.Show(s) End Sub End Class '-------------------------------------------------------- Public Class Form1 Inherits System.WinForms.Form Public Sub New() MyBase.New() Form1 = Me 'This call is required by the Win Form Designer. InitializeComponent() 'TODO: Add any initialization after the InitializeComponent() call End Sub 'Form overrides dispose to clean up the component list. Public Overrides Sub Dispose() MyBase.Dispose() components.Dispose() End Sub #Region " Windows Form Designer generated code " ........ #End Region Protected Sub Form1_Click( ByVal sender As Object, ByVal e As System.EventArgs) Dim a As New Example() a.Display() a.Display("Taiwan") a.Display(80) a.Display(100.5) End Sub End Class
此程序输出如下﹕ **** Taiwan 80 102.5
这Example类别比较特殊﹐没有资料成员﹔但含有一个程序成员叫Display() 。而Display()有 4个不同之版本(定义)﹐可任君(计算机)挑选。计算机藉比对自变量来挑选「最相配」之Display()程序。 例如﹕计算机执行到指令── a.Display("Taiwan")
由于自变量── "Taiwan"是字符串﹐其型态应配上String﹐所以计算机挑选并且执行第 4个程序── Display( ByVal s As String ) 。同理﹐当计算机执行到指令── a.Display(100.5)
由于自变量──100.5之型态为Double﹐所以计算机选上并执行第 3个Display()程序── Display(ByVal f As Double )。同一程序名称但有数个不同之定义﹐各有不同之自变量及内部指令﹐此种现象就是「程序的多重定义」。
请再看个例子──
'ex02.bas Imports System.ComponentModel Imports System.Drawing Imports System.WinForms '-------------------------------------------------- Class Sum Private s As Integer Public Overloads Sub Add() s = 3 + 5 End Sub Public Overloads Sub Add(ByVal x As Integer) s = x + 5 End Sub Public Overloads Sub Add(ByVal x As Integer, ByVal y As Integer) s = x + y End Sub Public Sub Show() MessageBox.Show("Sum = " + str(s)) End Sub End Class '--------------------------------------------------- Public Class Form1 Inherits System.WinForms.Form Public Sub New() MyBase.New() Form1 = Me 'This call is required by the Win Form Designer. InitializeComponent() 'TODO: Add any initialization after the InitializeComponent() call End Sub 'Form overrides dispose to clean up the component list. Public Overrides Sub Dispose() MyBase.Dispose() components.Dispose() End Sub #Region " Windows Form Designer generated code " ........ #End Region Protected Sub Form1_Click( ByVal sender As Object, ByVal e As System.EventArgs) Dim a As New Sum() a.Add() a.Show() a.Add(80) a.Show() Dim b As New Sum() b.Add(100, 27) b.Show() End Sub End Class
此程序输出如下﹕ Sum = 8 Sum = 85 Sum = 127
当计算机执行到指令── b.Add( 100, 27 ),由于有两个自变量﹐且型态皆为Integer﹔计算机就选上并执行第三个Add() 程序。此时计算机把100传给x﹐而27传给y。这多重定义之观念﹐也常用于建构者程序上。例如﹕
'ex03.bas Imports System.ComponentModel Imports System.Drawing Imports System.WinForms '--------------------------------------------------- Class Rectangle Private height As Integer, Width As Integer Public Overloads Sub New() height = 0 width = 0 End Sub Public Overloads Sub New(ByVal k As Integer) height = k width = k End Sub Public Overloads Sub New(ByVal h As Integer, ByVal w As Integer) height = h width = w End Sub Public Sub ShowArea() MessageBox.Show("Area = " + str(height * width)) End Sub End Class '--------------------------------------------------- Public Class Form1 Inherits System.WinForms.Form Public Sub New() MyBase.New() Form1 = Me 'This call is required by the Win Form Designer. InitializeComponent() 'TODO: Add any initialization after the InitializeComponent() call End Sub 'Form overrides dispose to clean up the component list. Public Overrides Sub Dispose() MyBase.Dispose() components.Dispose() End Sub #Region " Windows Form Designer generated code " ....... #End Region Protected Sub Form1_Click( ByVal sender As Object, ByVal e As System.EventArgs) Dim r1 As New Rectangle() Dim r2 As New Rectangle(8) Dim r3 As New Rectangle(5, 6) r1.ShowArea() r2.ShowArea() r3.ShowArea() End Sub End Class
此程序输出﹕ Area = 0 Area = 64 Area = 30
宣告对象时﹐若未给予自变量值﹐计算机呼叫New()﹔若给一个自变量值── 8﹐就呼叫 New(ByVal k As Integer) ﹔若给二个自变量值──5 及 6﹐则呼叫New(ByVal h As Integer, ByVal w As Integer)。请再看一个例子:
'ex04.bas Imports System.ComponentModel Imports System.Drawing Imports System.WinForms '------------------------------------------------------------------------------------------------- Class Rectangle Private height As Integer, Width As Integer Public Sub New(ByVal h As Integer, ByVal w As Integer) height = h width = w End Sub Public Function Area() As Integer Area = height * width End Function Public Overloads Function CompareWith(ByVal a As Integer) As Integer Dim d As Integer d = Area() - a If d <> 0 Then CompareWith = 1 Else CompareWith = 0 End If End Function Public Overloads Function CompareWith(ByVal r As Rectangle) As Integer Dim d As Integer d = Area() - r.Area() If d <> 0 Then d = 1 End If CompareWith = d End Function Public Overloads Function CompareWith( ByVal x As Rectangle, ByVal y As Rectangle) As Integer Dim d As Integer d = x.Area() - y.Area() If d <> 0 Then d = 1 End If CompareWith = d End Function End Class '---------------------------------------------------------------------------------------------- Public Class Form1 Inherits System.WinForms.Form Public Sub New() MyBase.New() Form1 = Me 'This call is required by the Win Form Designer. InitializeComponent() 'TODO: Add any initialization after the InitializeComponent() call End Sub 'Form overrides dispose to clean up the component list. Public Overrides Sub Dispose() MyBase.Dispose() components.Dispose() End Sub #Region " Windows Form Designer generated code " ........ #End Region Protected Sub Form1_Click( ByVal sender As Object, ByVal e As System.EventArgs) Dim r1 As New Rectangle(10, 50) Dim r2 As New Rectangle(20, 25) If r1.CompareWith(400) = 0 Then MessageBox.Show("EQUAL") Else MessageBox.Show("NOT EQUAL") End If If r1.CompareWith(r2) = 0 Then MessageBox.Show("EQUAL") Else MessageBox.Show("NOT EQUAL") End If If r1.CompareWith(r1, r2) = 0 Then MessageBox.Show("EQUAL") Else MessageBox.Show("NOT EQUAL") End If End Sub End Class
此程序输出﹕ NOT EQUAL EQUAL EQUAL
如此﹐CompareWith()程序就有三种用途了﹔如果您想增加其它用途﹐可尽情地再定义它。r1.CompareWith(400)呼叫第1个CompareWith(),比比看r1面积是否大于400;r1.ComapreWith(r2) 呼叫第2个CompareWith(),比比看r1面积是否大于r2的面积;r1.ComapreWith(r1, r2) 比比看r1面积是否大于r2的面积。如果没有使用多重定义方法,这三个程序名称不能相同。例如﹕上述程序可改写为──
'ex05.bas Imports System.ComponentModel Imports System.Drawing Imports System.WinForms '------------------------------------------------------------------------------------------- Class Rectangle Private height As Integer, Width As Integer Public Sub New(ByVal h As Integer, ByVal w As Integer) height = h width = w End Sub Public Function Area() As Integer Area = height * width End Function Public Function CompareWithInteger(ByVal a As Integer) As Integer Dim d As Integer d = Area() - a If d <> 0 Then d = 1 End If CompareWithInteger = d End Function Public Function CompareWithRectangle(ByVal r As Rectangle) As Integer Dim d As Integer d = Area() - r.Area() If d <> 0 Then d = 1 End If CompareWithRectangle = d End Function Public Function CompareTwoRectangle( ByVal x As Rectangle, ByVal y As Rectangle) As Integer Dim d As Integer d = x.Area() - y.Area() If d <> 0 Then d = 1 End If CompareTwoRectangle = d End Function End Class '--------------------------------------------------------------------------------------------- Public Class Form1 Inherits System.WinForms.Form Public Sub New() MyBase.New() Form1 = Me 'This call is required by the Win Form Designer. InitializeComponent() 'TODO: Add any initialization after the InitializeComponent() call End Sub 'Form overrides dispose to clean up the component list. Public Overrides Sub Dispose() MyBase.Dispose() components.Dispose() End Sub #Region " Windows Form Designer generated code " ........ #End Region Protected Sub Form1_Click( ByVal sender As Object, ByVal e As System.EventArgs) Dim r1 As New Rectangle(10, 50) Dim r2 As New Rectangle(20, 25) If r1.CompareWithInteger(400) = 0 Then MessageBox.Show("ggg EQUAL") Else MessageBox.Show("NOT EQUAL") End If If r1.CompareWithRectangle(r2) = 0 Then MessageBox.Show("EQUAL") Else MessageBox.Show("NOT EQUAL") End If If r1.CompareTwoRectangle(r1, r2) = 0 Then MessageBox.Show("EQUAL") Else MessageBox.Show("NOT EQUAL") End If End Sub End Class
此程序输出﹕ NOT EQUAL EQUAL EQUAL
由于各程序名称不相同,您就得记忆各程序之名字﹐徒增记忆负担而且易于犯错﹐并不合乎人们生活习惯。因之﹐VB的多重定义观念﹐能增加程序之弹性及亲切感。 程序多重定义情形并不限于单一类别之内,也可以发生于父子类别之间。例如:
'ex06.bas Imports System.ComponentModel Imports System.Drawing Imports System.WinForms '------------------------------------------------------------------------------------------ Public Class Person Private name As String Private age As Integer Public Sub New() End Sub Public Sub SetValue(ByVal na As String, ByVal a As Integer) name = na age = a End Sub Public Function birthDay() As Integer birthDay = 2001 - age End Function Public Sub Display() Messagebox.Show("Name: " + name + " Age: " + str(age)) End Sub End Class
Public Class Teacher Inherits Person Private salary As Decimal Public Overloads Sub SetValue( ByVal na As String, ByVal a As Integer, ByVal sa As Decimal) SetValue(na, a) salary = sa End Sub Public Sub pr() MyBase.Display() Messagebox.Show("Salary: " + str(salary)) End Sub End Class
Public Class Student Inherits Person Private student_number As Integer Public Overloads Sub SetValue( ByVal na As String, ByVal a As Integer, ByVal no As Integer) SetValue(na, a) student_number = no End Sub Public Sub pr() MyBase.Display() Messagebox.Show("StudNo: " + str(student_number)) End Sub End Class '----------------------------------------------------------------------------------------- Public Class Form1 Inherits System.WinForms.Form Public Sub New() MyBase.New() Form1 = Me 'This call is required by the Win Form Designer. InitializeComponent() 'TODO: Add any initialization after the InitializeComponent() call End Sub 'Form overrides dispose to clean up the component list. Public Overrides Sub Dispose() MyBase.Dispose() components.Dispose() End Sub #Region " Windows Form Designer generated code " ........ #End Region Protected Sub Form1_Click( ByVal sender As Object, ByVal e As System.EventArgs) Dim x As New Person() x.SetValue("Alvin", 32) Dim y As New Student() y.SetValue("Tom", 36, 11138) x.Display() y.pr() End Sub End Class
Teacher类别从Person继承了SetValue() ── SetValue(ByVal na As String, ByVal a As Integer)
自己又重复定义一个新的SetValue()程序── SetValue(ByVal na As String, ByVal a As Integer, ByVal no As Integer)
共有两个SetValue()可用。指令x.SetValue("Alvin", 32)呼叫第1个SetValue();指令y.SetValue("Tom", 36, 11138)呼叫第1个SetValue()。 兹在扩充一个子类别如下: 'ex07.bas Imports System.ComponentModel Imports System.Drawing Imports System.WinForms '------------------------------------------------------------------------------------------ Public Class Person Private name As String Private age As Integer Public Sub New() End Sub Public Sub SetValue(ByVal na As String, ByVal a As Integer) name = na age = a End Sub Public Function birthDay() As Integer birthDay = 2001 - age End Function Public Overridable Sub Display() Messagebox.Show("Name: " + name + " Age: " + str(age)) End Sub End Class
Public Class Teacher Inherits Person Private salary As Decimal Public Overloads Sub SetValue( ByVal na As String, ByVal a As Integer, ByVal sa As Decimal) SetValue(na, a) salary = sa End Sub Public Overrides Sub Display() MyBase.Display() Messagebox.Show("Salary: " + str(salary)) End Sub End Class
Public Class Student Inherits Person Private student_number As Integer Public Overloads Sub SetValue( ByVal na As String, ByVal a As Integer, ByVal no As Integer) SetValue(na, a) student_number = no End Sub Public Overrides Sub Display() MyBase.Display() Messagebox.Show("StudNo: " + str(student_number)) End Sub End Class '----------------------------------------------------------------------------------------- Public Class Form1 Inherits System.WinForms.Form Public Sub New() MyBase.New() Form1 = Me 'This call is required by the Win Form Designer. InitializeComponent() 'TODO: Add any initialization after the InitializeComponent() call End Sub 'Form overrides dispose to clean up the component list. Public Overrides Sub Dispose() MyBase.Dispose() components.Dispose() End Sub #Region " Windows Form Designer generated code " ........ #End Region Protected Sub Form1_Click( ByVal sender As Object, ByVal e As System.EventArgs) Dim x As New Person() x.SetValue("Alvin", 32) Dim y As New Student() y.SetValue("Tom", 36, 11138) x.Display() y.Display() End Sub End Class
此程序输出﹕ Name: Alvin Age: 32 Name: Tom Age: 36 StudNo: 11138
此时﹐Student 类别含有两个SetValue()程序,一个是从Person类别继承而来,另一个是自行定义的。如果上述Form1_Click()内的指令更改如下:
Dim y As New Student() y.SetValue("Tom", 36, 5000.25) 'Error! y.Display()
虽然SetValue("Tom", 36, 5000.25)合乎Teacher的SetValue()程序的参数,但是Student并非Person的子类别,没有继承Student的SetValue(),所以错了。n

|