@adamhand
2019-02-14T04:08:21.000000Z
字数 2637
阅读 998
Go 通过接口来实现多态。
一个类型如果定义了接口的所有方法,那它就隐式地实现了该接口。
通过一个程序我们来理解 Go 语言的多态,它会计算一个组织机构的净收益。假设这个虚构的组织所获得的收入来源于两个项目:fixed billing 和 time and material。该组织的净收益等于这两个项目的收入总和。假设货币单位是美元。因此货币只需简单地用 int 来表示。
程序如下:
package mainimport "fmt"/*收益接口。包含了两个方法:calculate() 计算并返回项目的收入,而 source() 返回项目名称。*/type Income interface {calculate() intsource() string}/*FixedBilling 项目的结构体类型有两个字段:projectName 表示项目名称,而 biddedAmount 表示组织向该项目投标的金额。*/type FixedBilling struct {projectName stringbiddedAmount int}/*TimeAndMaterial项目结构体类型拥有三个字段名:projectName、noOfHours 和 hourlyRate。*/type TimeAndMaterial struct {projectName stringnoOfHours inthourlyRate int}/*实现接口*/func (fb FixedBilling)calculate() int {return fb.biddedAmount}func (fb FixedBilling)source() string {return fb.projectName}func (tm TimeAndMaterial)calculate() int {return tm.hourlyRate * tm.noOfHours}func (tm TimeAndMaterial)source() string {return tm.projectName}/*计算收益根据 Income 接口的具体类型,程序会调用不同的 calculate() 和 source() 方法于是,在 calculateNetIncome 函数中就实现了多态。*/func calculateIncome(ic []Income) {var totalIncome int = 0for _, income := range ic{fmt.Printf("income from %s is $%d\n", income.source(), income.calculate())totalIncome += income.calculate()}fmt.Printf("total income is $%d\n", totalIncome)}func main() {project1 := FixedBilling{projectName: "Project 1", biddedAmount: 5000}project2 := FixedBilling{projectName: "Project 2", biddedAmount: 10000}project3 := TimeAndMaterial{projectName: "Project 3", noOfHours: 160, hourlyRate: 25}incomeStreams := []Income{project1, project2, project3}calculateIncome(incomeStreams)}
上述程序的执行结果为:
income from Project 1 is $5000income from Project 2 is $10000income from Project 3 is $4000total income is $19000
假设前面的组织通过广告业务,建立了一个新的收益流(Income Stream)。添加它非常简单,并且计算总收益也很容易,无需对 calculateNetIncome 函数进行任何修改。这就是多态的好处。
首先定义 Advertisement 类型,并在 Advertisement 类型中定义 alculate() 和 source() 方法。
Advertisement 类型有三个字段,分别是 adName、CPC(每次点击成本)和 noOfClicks(点击次数)。广告的总收益等于 CPC 和 noOfClicks 的乘积。
type Advertisement struct {adName stringCPC intnoOfClicks int}func (ad Advertisement)calculate() int {return ad.noOfClicks * ad.CPC}func (ad Advertisement)source() string {return ad.adName}
稍微修改一下 main 函数,创建了两个广告项目,即 bannerAd 和 popupAd。incomeStream,把新的收益流添加进来。
func main() {project1 := FixedBilling{projectName: "Project 1", biddedAmount: 5000}project2 := FixedBilling{projectName: "Project 2", biddedAmount: 10000}project3 := TimeAndMaterial{projectName: "Project 3", noOfHours: 160, hourlyRate: 25}bannerAd := Advertisement{adName: "Banner Ad", CPC: 2, noOfClicks: 500}popupAd := Advertisement{adName: "Popup Ad", CPC: 5, noOfClicks: 750}incomeStreams := []Income{project1, project2, project3, bannerAd, popupAd}calculateNetIncome(incomeStreams)}
然后程序的输出结果Wie:
income from Project 1 is $5000income from Project 2 is $10000income from Project 3 is $4000income from Banner Ad is $1000income from Popup Ad is $3750total income is $23750