2011-01-09 3 views
6

In C ich so etwas wie dieseSubklassifizieren in google gehen

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); 

Mit diesem Ansatz tut, kann ich jede Struktur passieren kann (Kreis, Rechteck, etc.), die struct Punkt als erstes Element hat. Wie kann ich das gleiche in google go?

+0

Das ist eine ziemlich verkorksten Beispiel, warum nicht verwenden: 'move (& C.P., 1, 2)', anstatt sich auf 'Speicherlayout des Circle'? Es wird auch nicht auf alle Formen skaliert, es sei denn, Sie definieren immer eine Form aus ihrem Schwerpunkt. –

+0

coz Circle interne Details werden nicht exportiert.ie Circle soll undurchsichtigen Typ für den Client sein. – Nyan

Antwort

7

Obwohl Go Typen und Methoden hat und ermöglicht einen objektorientierten Programmierstil , gibt es keine Art Hierarchie. Das Konzept der "Schnittstelle" in Go bietet einen anderen Ansatz , die wir glauben, ist einfach zu bedienen und in einige Möglichkeiten allgemeiner. Es gibt auch Möglichkeiten zum Einbetten von Typen in anderen Typen bieten etwas analoges-aber nicht identisch mit Unterklassen. Is Go an object-oriented language?, FAQ.

Zum Beispiel

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

Dies ist nicht dasselbe wie C-Code. Move() Code ist für jeden Typ hier doppelt vorhanden ... – Nyan

+2

PeterSO's Antwort ist idiomatisch Go; Go erlaubt nicht, einen Zeiger auf einen anderen Zeiger zu werfen, sondern nur einen Zeiger auf eine passende Schnittstelle zu werfen - daher hat er eine Schnittstelle und eine Anzahl von Typen definiert, die daran hafteten. – swdunlop

11

Eigentlich gibt es einen einfacheren Weg, es zu tun, die das Beispiel der OP ähnlicher ist:

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) 

Beachten Sie auch, dass Kreis würde auch erfüllen die Mover-Schnittstelle, die PeterSO gepostet hat.

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