2012-05-08 2 views
10

Come posso garantire che un tipo implementa un'interfaccia in fase di compilazione? Il modo tipico per farlo è di non riuscire ad assegnare le interfacce di supporto da quel tipo, tuttavia ho diversi tipi che vengono solo convertiti in modo dinamico. A runtime questo genera messaggi di errore molto burberi, senza la migliore diagnostica fornita per errori di compilazione. È anche molto scomodo trovare in fase di esecuzione che i tipi che mi aspettavo supportino le interfacce, in realtà no.Verificare che un tipo implementa un'interfaccia in fase di compilazione in Go

+0

In che lingua? – EJP

+0

@EJP: dovrebbe essere _go_, la lingua di google – themarcuz

risposta

10

Supponendo che la domanda riguardi Go, ad es.

var _ foo.RequiredInterface = myType{} // or &myType{} or [&]myType if scalar 

come TLD verificherà che per voi in fase di compilazione.

EDIT: s/[*]/&/

EDIT2: s/manichino/_ /, grazie Atom

+4

Puoi scrivere '_' invece di' dummy'. –

+1

Sono affascinato dalla notazione di modifica in stile sed. – Matt

1

Ti piace questa:

http://play.golang.org/p/57Vq0z1hq0

package main 

import(
    "fmt" 
) 

type Test int 

func(t *Test) SayHello() { 
    fmt.Println("Hello"); 
} 

type Saluter interface{ 
    SayHello() 
    SayBye() 
} 

func main() { 
    t := Saluter(new(Test)) 
    t.SayHello() 
} 

produrrà :

prog.go:19: cannot convert new(Test) (type *Test) to type Saluter: 
    *Test does not implement Saluter (missing SayBye method) 
-3

Non mi piace l'idea di fare errori nel compilatore inserendo linee fittizie nel codice principale. Questa è una soluzione intelligente che funziona, ma preferisco scrivere un test per questo scopo.

Supponendo che abbiamo:

type Intfc interface { Func() } 
type Typ int 
func (t Typ) Func() {} 

Questo test consente di verificare Typ implementa Intfc:

package main 

import (
    "reflect" 
    "testing" 
) 

func TestTypes(t *testing.T) { 
    var interfaces struct { 
     intfc Intfc 
    } 
    var typ Typ 
    v := reflect.ValueOf(interfaces) 
    testType(t, reflect.TypeOf(typ), v.Field(0).Type()) 
} 

// testType checks if type t1 implements interface t2 
func testType(t *testing.T, t1, t2 reflect.Type) { 
    if !t1.Implements(t2) { 
     t.Errorf("%v does not implement %v", t1, t2) 
    } 
} 

È possibile controllare tutti i tipi e le interfacce aggiungendoli a TestTypes funzione. I test di scrittura per Go vengono introdotti here.

+1

Eh, no. Scrivere un caso di test usando il reflection solo per evitare il controllo statico del tipo di un compilatore è IMO non consigliabile. – zzzz

+0

Cosa c'è di sbagliato in questo? – Mostafa

+1

Go è una lingua tipizzata in modo statico. Cosa c'è di sbagliato con un controllo di tipo statico? Il controllo dinamico del tipo è ragionevole se il controllo del tipo statico non è possibile, IMHO. – zzzz

-1
package main 

import (
    "fmt" 
) 

type Sayer interface { 
    Say() 
} 

type Person struct { 
    Name string 
} 

func(this *Person) Say() { 
    fmt.Println("I am", this.Name) 
} 

func main() { 
    person := &Person{"polaris"} 

    Test(person) 
} 

func Test(i interface{}) { 
    //!!here ,judge i implement Sayer 
    if sayer, ok := i.(Sayer); ok { 
     sayer.Say() 
    } 
} 

L'esempio di codice è qui: http://play.golang.org/p/22bgbYVV6q

2

Nel linguaggio Go non c'è "attrezzi" dichiarazione di progettazione. L'unico modo per chiedere al compilatore di verificare che il tipo T implementa l'interfaccia I tentando un assegnamento (sì, uno fittizio :). Nota, Go lang differenzia i metodi dichiarati sulla struttura e sul puntatore, usa quello giusto nel controllo dell'assegnazione!

type T struct{} 
var _ I = T{}  // Verify that T implements I. 
var _ I = (*T)(nil) // Verify that *T implements I. 

Leggi FAQ per i dettagli Why doesn't Go have "implements" declarations?

+0

[http://play.golang.org/p/UNXt7MlmX8](http://play.golang.org/p/UNXt7MlmX8) per evidenziare la differenza tra il puntatore e i controlli di assegnazione della struttura –