Last active
August 29, 2015 14:17
-
-
Save damienstanton/517462a94c999063d71d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| ------------------ Object Orientation in Go -------------------------------- | |
| Polymorphism | |
| Method Implementation (using value or pointer receivers) | |
| Interfaces | |
| Class Inheritance (Type Embedding) | |
| */ | |
| package main | |
| import "fmt" | |
| // Go type of interface, a named collection of method signatures | |
| type notifier interface { | |
| notify() | |
| } | |
| // Go type of struct, analogous to classes in other languages | |
| type user struct { | |
| name string | |
| email string | |
| } | |
| // Admin type has an "inner type" of user | |
| // Thus admin *extends* user | |
| type admin struct { | |
| user | |
| level string | |
| } | |
| // To implement an interface, simply call a pointer receiver method with the appropriate method signature. | |
| // One might call this "duck method typing" | |
| func (u *user) notify() { | |
| fmt.Printf("User: Sending email to %s<%s>\n", u.name, u.email) | |
| } | |
| /* | |
| ------ When to use value vs. pointer receivers ------- | |
| | Does the method need to modify the receiver? | |
| \__ the receiver MUST be a pointer | |
| | Does the method need to be passed a copy of the value? | |
| \__ the receiver MUST be a value | |
| | Consistency and efficiency | |
| \__ if some of the methods of the type must have pointer receivers, the rest should too. | |
| \__ if the receiver is large, it is much cheaper to use a pointer receiver. | |
| */ | |
| // changeEmail implements a method with a pointer receiver | |
| func (u *user) changeEmail(email string) { | |
| u.email = email | |
| } | |
| // Implement an interface using a different pointer | |
| func (a *admin) notify() { | |
| fmt.Printf("User: Sending email to administrator %s<%s>\n", a.name, a.email) | |
| } | |
| // sendNotification accepts values that implement the notifier interface | |
| func sendNotification(n notifier) { | |
| n.notify() | |
| } | |
| func main() { | |
| // Values of type user can be used to call methods declared with a value receiver | |
| u := &user{"Brennan", "[email protected]"} | |
| // Pass a pointer of type user to the sender function | |
| sendNotification(u) | |
| // In one statement, create a value of type admin, initializing both the admin's fields | |
| // as well as the inner type(user)'s fields. | |
| ad := admin{ | |
| user: user{ | |
| name: "Damien Stanton", | |
| email: "[email protected]", | |
| }, | |
| level: "sudo", | |
| } | |
| // because only the inner type actually implements the interface, the inner | |
| // type's implementation of the interface is promoted to the outer type... | |
| // ...thus it can be called via the implementation | |
| sendNotification(&ad) | |
| // ...one can also access a method by passing the pointer of an outer type | |
| //to a direct call to that method via the inner type | |
| ad.user.notify() | |
| // ...or the outer type | |
| ad.notify() | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment