Notas de estudio de Go (71): interfaz de interfaz de Go (definición de interfaz, implementación de interfaz, llamada de interfaz, receptor de valor, receptor de puntero)

1. Definición de la interfaz

Una interfaz es un acuerdo con la persona que llama, es un tipo muy abstracto y no necesita estar vinculado a detalles de implementación específicos. Interfaz de hacer es definir buena convención, informe a la persona que llama lo que pueden hacer, pero no sé su aplicación interna, lo que hemos visto y el tipo específico, tales como int, map, sliceetc., no son los mismos.

Definir y estructurar la interfaz es ligeramente diferente, aunque todo para typecomenzar con la palabra clave, pero la interfaz de palabras clave interfacerepresenta el tipo de interfaz personalizada.

Esa persones una interfaz, que tiene dos métodos sayName() stringy sayAge() int, como un todo, se muestra en el siguiente código:

type person interface {
    
    
	sayName() string
	sayAge() int
}
}

Para personla interfaz, le dirá a la persona que llama a través de su sayName()cadena de nombre de método de adquisición, a través de su sayAge()método de adquisición de edad, cuál es la interfaz acordada. En cuanto a cómo se obtiene la cadena y cómo se ve, a la interfaz no le importa, y al llamador no necesita preocuparse, porque esto lo hace el implementador de la interfaz.

2. Implementación de la interfaz

La interfaz debe ser implementada por un tipo particular a studentla estructura, por ejemplo,

type student struct {
    
    
	name string
	age  int
}

Se logra personinterfaces, como se muestra en el siguiente código:

func (s student) sayName() string {
    
    
	fmt.Printf("name is %v\n", s.name)
	return s.name
}

func (s student) sayAge() int {
    
    
	fmt.Printf("name is %v\n", s.age)
	return s.age
}

Escriba estructura para studentdefinir un método que en la firma del método, y una interfaz (nombre, parámetros y valores de retorno) lo mismo, por lo que la estructura studentse realiza personinterfaz.

Nota: Si una interfaz tiene varios métodos, se considera que cada método que necesita implementar la interfaz implementa la interfaz.

3. Asignación de interfaz

Asignación de interfaz Godividida en los siguientes dos idiomas de situaciones:

  • Asigne la instancia del objeto a la interfaz;
  • Asignar una interfaz a otra interfaz.

3.1 Asignar instancia de objeto a la interfaz

Primero, analice la asignación de un cierto tipo de instancia de objeto a la interfaz, que requiere que la instancia de objeto implemente todos los métodos requeridos por la interfaz, de la siguiente manera:

type Integer int

func (a Integer) Less(b Integer) bool {
    
    
	return a < b
}

func (a *Integer) Add(b Integer) {
    
    
	*a += b
}

En consecuencia, definimos la interfaz de la LessAddersiguiente manera:

type LessAdder interface {
    
    
	Less(b Integer) bool
	Add(b Integer)
}

Ahora hay una pregunta: Supongamos que definimos los Integertipos de instancia de un objeto, ¿cómo asignarlo a LessAdderla interfaz?
¿Debo usar la siguiente declaración (1) o declaración (2)?

var a Integer = 1
var b LessAdder = &a ... (1)
var b LessAdder = a ... (2)

La respuesta es que debe usarse la oración (1). La razón es que el Golenguaje puede basarse en las siguientes funciones:

func (a Integer) Less(b Integer) bool {
    
    
	return a < b
}

Genere automáticamente un nuevo Less()método:

func (a *Integer) Less(b Integer) bool {
    
    
	return (*a).Less(b)
}

Por lo tanto, el tipo *Integerexiste ambos Less()métodos, hay Add()métodos para cumplir con LessAdderla interfaz.
Por otro lado, según

	func (a *Integer) Add(b Integer)

Esta función no puede generar automáticamente el siguiente método de miembro:

func (a Integer) Add(b Integer) {
    
    
	(&a).Add(b)
}

Debido a que el (&a).Add()cambio es solo una función de los parámetros a, sujeto a influencias externas no es práctico de operar, lo cual no es consistente con las
expectativas de los usuarios.

Por lo tanto, el Goidioma no genera automáticamente esta función para él. Por lo tanto, el tipo Integerhay solo Less()un método, la falta de Add()un método, no satisface LessAdderla interfaz, por lo tanto, las declaraciones anteriores (2) no se pueden asignar.

Para demostrar aún más el razonamiento anterior, es posible que deseemos definir una Lesserinterfaz de la siguiente manera:

type Lesser interface {
    
    
	Less(b Integer) bool
}

Luego defina una Integerinstancia de objeto de tipo, asígnela a Lesserla interfaz:

var a Integer = 1
var b1 Lesser = &a ... (1)
var b2 Lesser = a ... (2)

Como esperábamos, tanto la declaración (1) como la declaración (2) se pueden compilar y pasar.

3.2 Asignar una interfaz a otra interfaz

En el Golenguaje, siempre que ambas interfaces tengan la misma lista de métodos (no importa el orden diferente), entonces son equivalentes, se pueden asignar entre sí.

4. Llamada de interfaz

Implementa personla interfaz después de su uso. En primer lugar, me gustaría definir una personinterfaz de función de impresión , de la siguiente manera:

func printPersonInfo(p person) {
    
    
	fmt.Printf("name is %v\n", p.sayName())
	fmt.Printf("age is %v\n", p.sayAge())
}

Esta función está definida printPersonInfo, recibe un persontipo de interfaz del parámetro y luego imprime la cadena de personinterfaz sayName()devuelta por el método, sayAge()el método devuelve Age

printPersonInfoLa ventaja de esta función es que está orientada a la interfaz de programación, siempre que un tipo implemente Stringerla interfaz, pueda imprimir una cadena de caracteres correspondiente y no controle las implementaciones específicas del tipo.

Dado que studentimplementa personla interfaz, tan variable stuen función de printPersonInfolos parámetros, se puede imprimir de la siguiente manera:

printPersonInfo(stu)

Producción

name is wohu
age is 20

Deje que la estructura teachertambién implemente personuna interfaz, como se muestra en el siguiente código:

type teacher struct {
    
    
	name string
	age  int
}

func (t teacher) sayName() string {
    
    
	return t.name
}

func (t teacher) sayAge() int {
    
    
	return t.age
}

Dado que la estructura teachertambién implementa la función de personinterfaz printPersonInfosin ningún cambio, se puede usar directamente, de la siguiente manera:

printPersonInfo(t)

Resultado de salida:

name is Jack
age is 40

Este es el beneficio de la interfaz orientada, siempre que la definición y la persona que llama cumplan con el acuerdo, puede usarlo, independientemente de la implementación específica. Los implementadores de la interfaz también pueden actualizar y refactorizar mejor sin ningún impacto, porque la convención de la interfaz no ha cambiado.

5. Receptor de valor y receptor de puntero

Ya sabemos que si quieres implementar una interfaz, debes implementar todos los métodos proporcionados por la interfaz, y al explicar el método en la última lección, defines un método, el cual tiene dos tipos: receptor tipo valor y receptor tipo puntero. . Se pueden invocar ambos métodos, ya que el Gocompilador realiza la conversión automáticamente, el valor del puntero de tipo y el tipo de destinatarios son equivalentes. Pero en la implementación de la interfaz, el receptor del tipo de valor y el receptor del tipo de puntero son diferentes, analizaré la diferencia entre los dos en detalle a continuación.

Lo anterior se ha verificado el tipo de estructura implementa personuna interfaz, entonces la estructura correspondiente al puntero también implementa esta interfaz. Usé el siguiente código para probar:

printPersonInfo(&s)

Resultado de salida:

name is wohu
age is 20

Después de la prueba, encontrará el tpuntero de la variable ya que un argumento pasado a printPersonInfola función es posible, compilar y ejecutar son normales. Esto demuestra que cuando un receptor de tipo de valor implementa una interfaz, tanto el tipo en sí como el tipo de puntero del tipo implementan la interfaz.

El receptor de ejemplo median ( s student) implementa personla interfaz, el tipo studenty el tipo de puntero que *studenthabría logrado personla interfaz.

Ahora, cambio el receptor a un tipo de puntero, como se muestra en el siguiente código:

func (s *student) sayName() string {
    
    
	return s.name
}

func (s *student) sayAge() int {
    
    
	return s.age
}

El receptor de tipo puntero modificado para encontrar la printPersonInfo(stu)compilación de código de línea de ejemplo no se pasa, lo que sugiere los siguientes errores:

demo.go:46:17: cannot use stu (type student) as type person in argument to printPersonInfo:
	student does not implement person (sayAge method has pointer receiver)

Lo que significa que el tipo studentno implementa personla interfaz. Esto prueba que cuando un receptor de tipo puntero implementa una interfaz, solo se considera que el tipo de puntero correspondiente implementa la interfaz.

para resumir:

  • Cuando el tipo de valor como destinatario, studenttipo y *studenttipo implementa esta interfaz;

  • Cuando el puntero escribe como receptor, solo *studentel tipo implementa esta interfaz;

Se puede encontrar que existen tipos que implementan interfaces *student, lo que también muestra que el tipo de puntero es más versátil, no importa qué tipo de receptor, puede implementar la interfaz.

package main

import "fmt"

type student struct {
    
    
	name string
	age  int
}

type teacher struct {
    
    
	name string
	age  int
}

type person interface {
    
    
	sayName() string
	sayAge() int
}

func (t teacher) sayName() string {
    
    
	return t.name
}

func (t teacher) sayAge() int {
    
    
	return t.age
}

func (s *student) sayName() string {
    
    
	// fmt.Printf("name is %v\n", s.name)
	return s.name
}

func (s *student) sayAge() int {
    
    
	// fmt.Printf("age is %v\n", s.age)
	return s.age
}

func printPersonInfo(p person) {
    
    
	fmt.Printf("name is %v\n", p.sayName())
	fmt.Printf("age is %v\n", p.sayAge())
}

func main() {
    
    
	stu := student{
    
    name: "wohu", age: 20}
	// t := teacher{name: "Jack", age: 40}
	printPersonInfo(stu)
	// printPersonInfo(t)

}

Supongo que te gusta

Origin blog.csdn.net/wohu1104/article/details/111242632
Recomendado
Clasificación