# [译] part 28: golang 的面向对象 — 多态

https://juejin.im/post/5cb0a776e51d456e361ed8b6

Go 中的多态性是在接口的帮助下实现的。正如我们已经讨论过的，接口可以在 Go 中隐式实现。如果类型为接口中声明的所有方法提供定义，则类型实现接口。让我们看看在接口的帮助下如何在 Go 中实现多态性。

## 使用接口实现多态

type Income interface {      calculate() int    source() string}

type FixedBilling struct {      projectName string    biddedAmount int}

FixedBilling项目有两个字段projectName，表示项目名称，biddedAmount是组织为项目出价的金额。

TimeAndMaterial结构表示按时间计算收益的项目

type TimeAndMaterial struct {      projectName string    noOfHours  int    hourlyRate int}

TimeAndMaterial结构有三个字段projectNamenoOfHourshourlyRate

func (fb FixedBilling) calculate() int {      return fb.biddedAmount}func (fb FixedBilling) source() string {      return fb.projectName}func (tm TimeAndMaterial) calculate() int {      return tm.noOfHours * tm.hourlyRate}func (tm TimeAndMaterial) source() string {      return tm.projectName}

func calculateNetIncome(ic []Income) {      var netincome int = 0    for _, income := range ic {        fmt.Printf("Income From %s = $%d\n", income.source(), income.calculate()) netincome += income.calculate() } fmt.Printf("Net income of organisation =$%d", netincome)}

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}    calculateNetIncome(incomeStreams)}

package mainimport (      "fmt")type Income interface {      calculate() int    source() string}type FixedBilling struct {      projectName string    biddedAmount int}type TimeAndMaterial struct {      projectName string    noOfHours  int    hourlyRate int}func (fb FixedBilling) calculate() int {      return fb.biddedAmount}func (fb FixedBilling) source() string {      return fb.projectName}func (tm TimeAndMaterial) calculate() int {      return tm.noOfHours * tm.hourlyRate}func (tm TimeAndMaterial) source() string {      return tm.projectName}func calculateNetIncome(ic []Income) {      var netincome int = 0    for _, income := range ic {        fmt.Printf("Income From %s = $%d\n", income.source(), income.calculate()) netincome += income.calculate() } fmt.Printf("Net income of organisation =$%d", netincome)}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}    calculateNetIncome(incomeStreams)}

Run in playground

Income From Project 1 = $5000 Income From Project 2 =$10000  Income From Project 3 = $4000 Net income of organisation =$19000

## 在上述代码中添加新的收入来源

type Advertisement struct {      adName     string    CPC        int    noOfClicks int}func (a Advertisement) calculate() int {      return a.CPC * a.noOfClicks}func (a Advertisement) source() string {      return a.adName}

Advertisement类型有三个字段：adNameCPC（每次点击费用）和noOfClicks（点击次数）。广告的总收入是CPCnoOfClicks的乘积。

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)}

package mainimport (      "fmt")type Income interface {      calculate() int    source() string}type FixedBilling struct {      projectName  string    biddedAmount int}type TimeAndMaterial struct {      projectName string    noOfHours   int    hourlyRate  int}type Advertisement struct {      adName     string    CPC        int    noOfClicks int}func (fb FixedBilling) calculate() int {      return fb.biddedAmount}func (fb FixedBilling) source() string {      return fb.projectName}func (tm TimeAndMaterial) calculate() int {      return tm.noOfHours * tm.hourlyRate}func (tm TimeAndMaterial) source() string {      return tm.projectName}func (a Advertisement) calculate() int {      return a.CPC * a.noOfClicks}func (a Advertisement) source() string {      return a.adName}func calculateNetIncome(ic []Income) {      var netincome int = 0    for _, income := range ic {        fmt.Printf("Income From %s = $%d\n", income.source(), income.calculate()) netincome += income.calculate() } fmt.Printf("Net income of organisation =$%d", netincome)}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)}

Run in playground

Income From Project 1 = $5000 Income From Project 2 =$10000  Income From Project 3 = $4000 Income From Banner Ad =$1000  Income From Popup Ad = $3750 Net income of organisation =$23750