Golang之路---03 面向对象——接口与多态

接口与多态

何为接口

  在面向对象的领域里,接口一般这样定义:接口定义一个对象的行为。接口只指定了对象应该做什么,至于如何实现这个行为(即实现细节),则由对象本身去确定。
  在 Go 语言中,接口就是方法签名(Method Signature)的集合。当一个类型定义了接口中的所有方法,我们称它实现了该接口。接口指定了一个类型应该具有的方法,并由该类型决定如何实现这些方法。

接口定义

  使用type关键字来定义接口
如下所示,定义了一个叫order的接口,接口要求必须实现printName方法

type order interface{
   printName()
}

接口的实现

如果有一个类型/结构体,实现了一个接口要求的所有方法,我们就可以称它实现了该接口。

接口实现多态

  一个接口,在不同对象上的不同表现。这就是多态。在 Go 语言中,是通过接口来实现的多态。

package main

import (
	"fmt"
	"strconv"
)

//定义一个接口
type order interface{
	countmoney() int
	paymoney() string
}

type hamburger struct{
	name string
	quantity int
	price int
}

func (ham hamburger) countmoney() (int){
	return ham.quantity*ham.price
}

func (ham hamburger) paymoney() (string){
	//strconv.Itoa() 可以将数字转换成对应的字符串类型的数字。
	return "所购买的" + strconv.Itoa(ham.quantity) + "个"+ham.name+"共计:" + strconv.Itoa(ham.countmoney()) + "元" 
}

type roastrice struct{
	name string
	quantity int  
	price int
}

func (roa roastrice) countmoney() (int){
	return roa.quantity*roa.price
}

func (roa roastrice) paymoney() (string){
	return "所购买的" + strconv.Itoa(roa.quantity) + "个"+roa.name+"共计:" + strconv.Itoa(roa.countmoney()) + "元" 
}

func calaulateSum(orders []order)(int){
	var sumPrice int
	for _,now := range orders{
		fmt.Println(now.paymoney())
		sumPrice += now.countmoney()
	}
    return sumPrice
}

func main(){
	ham := hamburger{
		"烤鸡汉堡",
		2,
		18,
	}

	rice := roastrice{
		"烤饭",
		5,
		2,
	}

	orders := []order{ham,rice}
	sumPrice := calaulateSum(orders)
	fmt.Printf("这顿饭共计%d元",sumPrice)
}

在这里插入图片描述

接口使用的注意事项

1.方法调用的限制

接口是一组固定的方法集,由于静态类型的限制,接口变量有时仅能调用其中特定的一些方法。
下面这段代码会报错


type Phone interface{
	call()
}

type iPhone struct{
	name string
}

func (ipone iPhone) call(){
	fmt.Println("Hello iPhone.")
}

func (iphone iPhone) send_wechat(){
	fmt.Println("Hello Wechat")
}

func main(){
	var phone Phone
	phone = iPhone{"xin's iphone"}
	phone.call()
	phone.send_wechat()
}

提示我们 Phone 类型的方法没有 send_wechat 的字段或方法。
在这里插入图片描述
原因也很明显,因为我们的phone对象显式声明为 Phone 接口类型,因此 phone调用的方法会受到此接口的限制。
修改方法:隐式实现 Phone 接口,如此一来,方法的调用就不会受到接口类型的约束。

	/* var phone Phone
	phone = iPhone{"xin's iphone"} */
	phone := iPhone{"xin's iphone"}
	phone.call()
	phone.send_wechat()
2.调用函数时的隐式转换

Golang 语言中的函数调用都是值传递的,变量会在方法调用前进行类型转换。
eg:下面一段是可以正常运行的代码

func printTpe(i interface{}){
	switch i.(type){
	case int:
		fmt.Println("参数的类型是 int")
	case string:
		fmt.Println("参数的类型是 string")
	}
}

func main(){
	a:=10
	printTpe(a)
}

但是如果你把函数内的内容搬到到外面来

func main(){
	a:=10
	switch a.(type){
	case int:
		fmt.Println("参数的类型是 int")
	case string:
		fmt.Println("参数的类型是 string")
	}
}

报错:
在这里插入图片描述
当一个函数接口 interface{} 空接口类型时,我们说它可以接收什么任意类型的参数(江湖上称之为无招胜有招)。就是把传入函数的参数值(注意:Go 语言中的函数调用都是值传递的)的类型隐式的转换成 interface{} 类型。
所以要想不通过接收空接口类型的函数进行类型判断,我们需要进行显示转换

func main(){
	a:=10
	switch interface{}(a).(type){
	case int:
		fmt.Println("参数的类型是 int")
	case string:
		fmt.Println("参数的类型是 string")
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值