pointers - remix - smart contracts ethereum
¿Por qué no se puede implementar la interfaz con receptores de puntero? (2)
Creo que la respuesta a esta pregunta necesita un enfoque más retrospectivo hacia la gramática y cómo implementarla a través de la ingeniería de software. (Disculpe la simplificación excesiva)
Primero, ¿un flashback rápido de qué son los
types
?
Son solo bloques de memoria con la lógica del compilador en la parte superior.
Lo que hace que una
array
diferente de una
string
es lo que el compilador nos permite hacer con esos bloques de memoria.
(Piense más profundamente y puede comenzar a darse cuenta de la verdadera diferencia entre
dynamically typed
idiomas
strongly typed
y
dynamically typed
).
Ahora, a continuación, debe darse cuenta de que los punteros son sus propios tipos por decir.
*variable
es un bloque de memoria diferente (también conocido como tipo) que la
variable
.
Es solo que el compilador siempre asume que el contenido de
*variable
siempre será una dirección a un bloque de memoria de tipo a la derecha de la declaración junto con otras restricciones / características que impone.
Entonces recapitulemos qué es una interfaz.
Definición pseudocientífica
: conjunto de requisitos para que cualquier ciudadano de primera clase sea de un tipo específico.
Traducido a la ingeniería de software: cualquier bloque de memoria (tipos) que tenga la misma estructura de memoria (piense en el
empaque de la estructura
) asociado a él como se describe en un contrato (
interface
) se puede pasar como con el
nombre de tipo
que menciona el contrato.
Ahora puedes comenzar a darte cuenta de eso cuando dices
func (f *Faz) Bar() string
es el bloque de memoria de
f
contiene una función, donde el tipo de
f
es
un puntero a
Faz
donde áreas
func (f Faz) Bar() string
es el bloque de memoria de
f
, donde el tipo de
f
es
Faz
Entonces, cuando está diciendo que una variable de tipo
*Faz
satisface un contrato, ¿cómo puede suponer que una variable de tipo
Faz
calificará como tipo de interfaz en el código?
Elija quién satisface su contrato, y solo ese tipo puede asumir el tipo de interfaz en su código.
Estoy confundido sobre por qué esto no se compila con:
aserción de tipo imposible: Faz no implementa Foo (el método de barra tiene receptor de puntero)
si hago el receptor para Faz.Bar un valor Faz en lugar de un puntero Faz, entonces se compila bien, pero pensé que siempre era mejor tener receptores punteros para que no se copiaran los valores.
package main
import (
"log"
)
func main() {
foo := New().(Faz)
log.Println(foo)
}
type Foo interface {
Bar() string
}
func New() Foo {
return &Faz{}
}
type Faz struct {
}
func (f *Faz) Bar() string {
return `Bar`
}
Porque es
*Faz
no
Faz
.
func main() {
foo := New().(*Faz)
log.Println(foo)
}