https://blog.csdn.net/u011957758/article/details/81150622
Prefacio
La interfaz es un movimiento de uso frecuente en la programación orientada a objetos y también es un medio muy importante para reflejar el polimorfismo.
Si. También hay interfaces en Golang.
Este artículo explicará la interfaz de Golang de una manera fácil de entender.
Después de 10 segundos, los siguientes puntos de conocimiento están a punto de llegar al campo de batalla:
1. ¿Por qué necesito una interfaz?
2. ¿Qué es la interfaz? ¿Cómo definir?
3. Primera experiencia de la interfaz en combate real
4. ¿Cómo probar si se ha implementado la interfaz?
5. Interfaz vacía y afirmación de tipo
6. Interfaz de valor cero
7. Un tipo implementa múltiples interfaces
8. La diferencia entre punteros y tipos de valor implementan interfaces
9. Interfaz anidada
texto
1. ¿Por qué necesito una interfaz?
En la mayoría de los casos, los datos pueden contener diferentes tipos, pero hay uno o más puntos en común, y estos puntos en común son la base de la abstracción. La herencia de Golang mencionada anteriormente resuelve el problema de es-un, la relación de herencia única. Pero cuando diferentes clases principales tienen el mismo comportamiento, la herencia única no se puede resolver.
Desde entonces, apareció la interfaz. La interfaz puede entenderse como una abstracción de un cierto aspecto, que puede ser de varios a uno (varios tipos implementan una interfaz), que también es una manifestación de polimorfismo . Resolvió el problema uno a uno anterior.
2. ¿Qué es la interfaz? ¿Cómo definir?
Qué
interfaz es un conjunto que contiene solo el nombre del método, los parámetros, el valor de retorno no es la realización específica del proceso de recolección .
Si se implementan todos los métodos de la interfaz, se considera que la interfaz está implementada y no es necesario agregar una declaración sobre el tipo .
Bajo esta explicación, profundice la impresión de que la interfaz en php se ve así:
//定义接口
interface base{
public function getName();
}
//学生类
class student implements base{
public function getName(){
echo "咖啡色的羊驼";
}
}
Aquí hay una palabra clave: implementos .
Tal declaración se llama explícita y en Golang la interfaz se implementa implícitamente . (Ver más abajo para un presagio)
definición
type interfaceName interface {
// 方法列表
GetName() string
}
3. Primera experiencia de combate real de interfaz
En la programación real, a todos les gusta terminar el nombre de la interfaz con er. Por supuesto, esto depende de las preferencias personales.
Código anterior:
package main
import (
"fmt"
)
// 定义一个接口
type People interface {
ReturnName() string
}
// 定义一个结构体
type Student struct {
Name string
}
// 定义结构体的一个方法。
// 突然发现这个方法同接口People的所有方法(就一个),此时可直接认为结构体Student实现了接口People
func (s Student) ReturnName() string {
return s.Name
}
func main() {
cbs := Student{Name:"咖啡色的羊驼"}
var a People
// 因为Students实现了接口所以直接赋值没问题
// 如果没实现会报错:cannot use cbs (type Student) as type People in assignment:Student does not implement People (missing ReturnName method)
a = cbs
name := a.ReturnName()
fmt.Println(name) // 输出"咖啡色的羊驼"
}
4. ¿Cómo probar si se ha implementado la interfaz?
Utilice el juicio de afirmación específico de la interfaz para lograr (se mencionará nuevamente a continuación para profundizar la impresión).
Sintaxis: x. (T)
tal gramática solo es adecuada para x es un tipo de interfaz
Siguiendo el ejemplo anterior, continúe con el código:
// 由于x.(T)只能是接口类型判断,所以传参时候,传入的是接口类型
// 为何test的类型可以是一个空接口?埋伏笔下文便知。
func CheckPeople(test interface{}) {
if _, ok := test.(People); ok {
fmt.Printf("Student implements People")
}
}
func main() {
cbs := Student{Name:"咖啡色的羊驼"}
CheckPeople(cbs) // Student implements People
}
5. Interfaz vacía y afirmación de tipo
Interfaz vacía
Una interfaz vacía es una interfaz que no contiene ningún método. Debido a esto, todos los tipos implementan interfaces vacías .
Aunque la interfaz vacía no juega ningún papel, la interfaz vacía es muy útil cuando se necesita almacenar cualquier tipo de valor, esto también responde a la pregunta anterior, ya que la interfaz vacía puede almacenar cualquier tipo de datos.
// 定义cbs为空接口
var cbs interface{}
var i int = 5
var s string = "Hello world"
// cbs可以存储任意类型的数值
cbs = i
cbs = s
Aserción de tipo
Dado que la interfaz vacía puede almacenar cualquier tipo, ¿cómo distinguir entre diferentes tipos?
Hay dos métodos de uso común: afirmación por coma y juicio de cambio .
Código anterior:
package main
import (
"fmt"
)
// 定义一个结构体
type Student struct {
Name string
}
// 类型断言
func main() {
Params := make([]interface{}, 3)
Params[0] = 88 // 整型
Params[1] = "咖啡色的羊驼" // 字符串
Params[2] = Student{Name: "cbs"} // 自定义结构体类型
// Comma-ok断言
for index, v := range Params {
if _, ok := v.(int); ok {
fmt.Printf("Params[%d] 是int类型 \n", index)
} else if _, ok := v.(string); ok {
fmt.Printf("Params[%d] 是字符串类型\n", index)
} else if _, ok := v.(Student); ok {
fmt.Printf("Params[%d] 是自定义结构体类型\n", index)
} else {
fmt.Printf("list[%d] 未知类型\n", index)
}
}
// switch判断
for index, v := range Params {
switch value := v.(type) {
case int:
fmt.Printf("Params[%d] 是int类型, 值:%d \n", index,value)
case string:
fmt.Printf("Params[%d] 是字符串类型, 值:%s\n", index,value)
case Student:
fmt.Printf("Params[%d] 是Person类型, 值:%s\n", index,value)
default:
fmt.Printf("list[%d] 未知类型\n", index)
}
}
}
6. Valor cero de la interfaz
El valor cero de la interfaz es nulo
package main
import (
"fmt"
)
type People interface {
GetName() string
}
// 输出 "cbs is nil 类型"
func main() {
var cbs People
if cbs == nil {
fmt.Println("cbs is nil 类型")
}
}
7. Un tipo implementa múltiples interfaces
package main
import (
"fmt"
)
type People interface {
ReturnName() string
}
type Role interface {
ReturnRole() string
}
type Student struct {
Name string
}
func (s Student) ReturnName() string {
return s.Name
}
func (s Student) ReturnRole() string {
return "学生"
}
func main() {
cbs := Student{Name: "咖啡色的羊驼"}
var a People // 定义a为People接口类型
var b Role // 定义b为Role接口类型
a = cbs // 由于Student实现了People所有方法,所以接口实现成功,可直接赋值
b = cbs // 由于Student实现了Role所有方法,所以接口实现成功,可直接赋值
name := a.ReturnName()
fmt.Println(name) // 输出"咖啡色的羊驼"
role := b.ReturnRole()
fmt.Println(role) // 输出"学生"
}
También explique una cosa: para lograr un cierto tipo de interfaz, puede haber otros métodos. Siempre que la implementación del método incluya la interfaz.
8. La diferencia entre el puntero y la interfaz de implementación del tipo de valor
package main
import (
"fmt"
)
type People interface {
ReturnName() string
}
type Student struct {
Name string
}
type Teacher struct {
Name string
}
func (s Student) ReturnName() string {
return s.Name
}
func (t *Teacher) ReturnName() string {
return t.Name
}
func main() {
cbs := Student{Name: "咖啡色的羊驼"}
sss := Teacher{Name: "咖啡色的羊驼的老师"}
// 值类型
var a People
a = cbs
name := a.ReturnName()
fmt.Println(name)
// 指针类型
// a = sss <- 这样写不行!!!
a = &sss // 由于是指针类型,所以赋值的时候需要加上&
name = a.ReturnName()
fmt.Println(name) // 输出"咖啡色的羊驼的老师"
}
"a = sss" si escribe así provocará un error:
cannot use sss (type Teacher) as type People in assignment:
Teacher does not implement People (ReturnName method has pointer receiver)
Debido a que el puntero del profesor implementa el método ReturnName, el profesor no lo implementa.
9. Anidación de interfaz
Similar a la herencia de interfaz de PHP, Golang también tiene su interfaz anidada.
package main
import (
"fmt"
)
type People interface {
ReturnName() string
}
type Role interface {
People // 接口嵌套
ReturnRole() string
}
type Student struct {
Name string
}
func (s Student) ReturnName() string {
return s.Name
}
func (s Student) ReturnRole() string {
return "学生"
}
func main() {
cbs := Student{Name: "咖啡色的羊驼"}
var a Role
a = cbs
name := a.ReturnName()
fmt.Println(name)
role := a.ReturnRole()
fmt.Println(role)
}