2011-01-09 19 views
6

En C que puede hacer algo como estosubclases en google ir

struct Point { 
    int x,y; 
} 

struct Circle { 
    struct Point p;  // must be first! 
    int rad; 
} 

void move(struct Point *p,int dx,int dy) { 
    .... 
} 

struct Circle c = .....; 
move((struct Point*)&c,1,2); 

uso de este enfoque, puedo pasar cualquier estructura (círculo, rectángulo, etc) que tiene un punto de estructura como el primer miembro. ¿Cómo puedo hacer lo mismo en Google Go?

+0

Eso es un ejemplo bastante mal estado en marcha, por qué no usar: 'movimiento (y partidos comunistas, 1, 2)' en lugar de depender de la distribución de la memoria del 'Circle'? Además, no se adapta a todas las formas, a menos que siempre definas una forma desde su baricentro. –

+0

coz Los detalles internos del círculo no se exportan. Se supone que el círculo es de tipo opaco para el cliente. – Nyan

Respuesta

7

Aunque Go tiene tipos y métodos y permite un estilo orientado a objetos de programación, no hay ningún tipo jerarquía. El concepto de "interfaz" en Go proporciona un enfoque diferente que creemos que es fácil de usar y en de algunas maneras más generales. También hay formas de incrustar tipos en otros tipos para proporcionar algo análogo, pero no idéntico a subclases. Is Go an object-oriented language?, FAQ.

Por ejemplo,

package main 

import "fmt" 

type Mover interface { 
    Move(x, y int) 
} 

type Point struct { 
    x, y int 
} 

type Circle struct { 
    point Point 
    rad int 
} 

func (c *Circle) Move(x, y int) { 
    c.point.x = x 
    c.point.y = y 
} 

type Square struct { 
    diagonal int 
    point Point 
} 

func (s *Square) Move(x, y int) { 
    s.point.x = x 
    s.point.y = y 
} 

func main() { 
    var m Mover 
    m = &Circle{point: Point{1, 2}} 
    m.Move(3, 4) 
    fmt.Println(m) 
    m = &Square{3, Point{1, 2}} 
    m.Move(4, 5) 
    fmt.Println(m) 
} 
+0

Esto no es lo mismo que el código C. El código Move() se duplica para cada tipo aquí ... – Nyan

+2

La respuesta de PeterSO es idiomática Go; Go no permite lanzar un puntero a otro puntero, solo proyecta un puntero a una interfaz coincidente; por lo tanto, ha definido una interfaz y una cantidad de tipos que se han adherido a ella. – swdunlop

11

En realidad, hay una manera más sencilla de hacerlo, lo que es más similar al ejemplo de la OP:

type Point struct { 
    x, y int 
} 

func (p *Point) Move(dx, dy int) { 
    p.x += dx 
    p.y += dy 
} 

type Circle struct { 
    *Point // embedding Point in Circle 
    rad int 
} 

// Circle now implicitly has the "Move" method 
c := &Circle{&Point{0, 0}, 5} 
c.Move(7, 3) 

Nótese también que Circle también cumpliría la interfaz de Mover que publicó PeterSO.

http://golang.org/doc/effective_go.html#embedding