improving chapter 2.6
This commit is contained in:
111
en/02.6.md
111
en/02.6.md
@@ -20,7 +20,6 @@ This combination of methods is called an interface and is implemented by both St
|
|||||||
|
|
||||||
An interface defines a set of methods, so if a type implements all the methods we say that it implements the interface.
|
An interface defines a set of methods, so if a type implements all the methods we say that it implements the interface.
|
||||||
```Go
|
```Go
|
||||||
|
|
||||||
type Human struct {
|
type Human struct {
|
||||||
name string
|
name string
|
||||||
age int
|
age int
|
||||||
@@ -39,33 +38,7 @@ type Employee struct {
|
|||||||
money float32
|
money float32
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Human) SayHi() {
|
// define interfaces
|
||||||
fmt.Printf("Hi, I am %s you can call me on %s\n", h.name, h.phone)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *Human) Sing(lyrics string) {
|
|
||||||
fmt.Println("La la, la la la, la la la la la...", lyrics)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *Human) Guzzle(beerStein string) {
|
|
||||||
fmt.Println("Guzzle Guzzle Guzzle...", beerStein)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Employee overloads Sayhi
|
|
||||||
func (e *Employee) SayHi() {
|
|
||||||
fmt.Printf("Hi, I am %s, I work at %s. Call me on %s\n", e.name,
|
|
||||||
e.company, e.phone) //Yes you can split into 2 lines here.
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Student) BorrowMoney(amount float32) {
|
|
||||||
s.loan += amount // (again and again and...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Employee) SpendSalary(amount float32) {
|
|
||||||
e.money -= amount // More vodka please!!! Get me through the day!
|
|
||||||
}
|
|
||||||
|
|
||||||
// define interface
|
|
||||||
type Men interface {
|
type Men interface {
|
||||||
SayHi()
|
SayHi()
|
||||||
Sing(lyrics string)
|
Sing(lyrics string)
|
||||||
@@ -84,6 +57,31 @@ type ElderlyGent interface {
|
|||||||
SpendSalary(amount float32)
|
SpendSalary(amount float32)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *Human) SayHi() {
|
||||||
|
fmt.Printf("Hi, I am %s you can call me on %s\n", h.name, h.phone)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Human) Sing(lyrics string) {
|
||||||
|
fmt.Println("La la, la la la, la la la la la...", lyrics)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Human) Guzzle(beerStein string) {
|
||||||
|
fmt.Println("Guzzle Guzzle Guzzle...", beerStein)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Employee overloads SayHi
|
||||||
|
func (e *Employee) SayHi() {
|
||||||
|
fmt.Printf("Hi, I am %s, I work at %s. Call me on %s\n", e.name,
|
||||||
|
e.company, e.phone) //Yes you can split into 2 lines here.
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Student) BorrowMoney(amount float32) {
|
||||||
|
s.loan += amount // (again and again and...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Employee) SpendSalary(amount float32) {
|
||||||
|
e.money -= amount // More vodka please!!! Get me through the day!
|
||||||
|
}
|
||||||
```
|
```
|
||||||
We know that an interface can be implemented by any type, and one type can implement many interfaces simultaneously.
|
We know that an interface can be implemented by any type, and one type can implement many interfaces simultaneously.
|
||||||
|
|
||||||
@@ -117,25 +115,28 @@ type Employee struct {
|
|||||||
money float32
|
money float32
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h Human) SayHi() {
|
|
||||||
fmt.Printf("Hi, I am %s you can call me on %s\n", h.name, h.phone)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h Human) Sing(lyrics string) {
|
|
||||||
fmt.Println("La la la la...", lyrics)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e Employee) SayHi() {
|
|
||||||
fmt.Printf("Hi, I am %s, I work at %s. Call me on %s\n", e.name,
|
|
||||||
e.company, e.phone) //Yes you can split into 2 lines here.
|
|
||||||
}
|
|
||||||
|
|
||||||
// Interface Men implemented by Human, Student and Employee
|
// Interface Men implemented by Human, Student and Employee
|
||||||
type Men interface {
|
type Men interface {
|
||||||
SayHi()
|
SayHi()
|
||||||
Sing(lyrics string)
|
Sing(lyrics string)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// method
|
||||||
|
func (h Human) SayHi() {
|
||||||
|
fmt.Printf("Hi, I am %s you can call me on %s\n", h.name, h.phone)
|
||||||
|
}
|
||||||
|
|
||||||
|
// method
|
||||||
|
func (h Human) Sing(lyrics string) {
|
||||||
|
fmt.Println("La la la la...", lyrics)
|
||||||
|
}
|
||||||
|
|
||||||
|
// method
|
||||||
|
func (e Employee) SayHi() {
|
||||||
|
fmt.Printf("Hi, I am %s, I work at %s. Call me on %s\n", e.name,
|
||||||
|
e.company, e.phone) //Yes you can split into 2 lines here.
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
mike := Student{Human{"Mike", 25, "222-222-XXX"}, "MIT", 0.00}
|
mike := Student{Human{"Mike", 25, "222-222-XXX"}, "MIT", 0.00}
|
||||||
paul := Student{Human{"Paul", 26, "111-222-XXX"}, "Harvard", 100}
|
paul := Student{Human{"Paul", 26, "111-222-XXX"}, "Harvard", 100}
|
||||||
@@ -167,7 +168,6 @@ func main() {
|
|||||||
value.SayHi()
|
value.SayHi()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
```
|
```
|
||||||
An interface is a set of abstract methods, and can be implemented by non-interface types. It cannot therefore implement itself.
|
An interface is a set of abstract methods, and can be implemented by non-interface types. It cannot therefore implement itself.
|
||||||
|
|
||||||
@@ -176,20 +176,24 @@ An interface is a set of abstract methods, and can be implemented by non-interfa
|
|||||||
An empty interface is an interface that doesn't contain any methods, so all types implement an empty interface. This fact is very useful when we want to store all types at some point, and is similar to void* in C.
|
An empty interface is an interface that doesn't contain any methods, so all types implement an empty interface. This fact is very useful when we want to store all types at some point, and is similar to void* in C.
|
||||||
```Go
|
```Go
|
||||||
// define a as empty interface
|
// define a as empty interface
|
||||||
var a interface{}
|
var void interface{}
|
||||||
var i int = 5
|
|
||||||
|
// vars
|
||||||
|
i := 5
|
||||||
s := "Hello world"
|
s := "Hello world"
|
||||||
|
|
||||||
// a can store value of any type
|
// a can store value of any type
|
||||||
a = i
|
void = i
|
||||||
a = s
|
void = s
|
||||||
```
|
```
|
||||||
|
|
||||||
If a function uses an empty interface as its argument type, it can accept any type; if a function uses empty interface as its return value type, it can return any type.
|
If a function uses an empty interface as its argument type, it can accept any type; if a function uses empty interface as its return value type, it can return any type.
|
||||||
|
|
||||||
### Method arguments of an interface
|
### Method arguments of an interface
|
||||||
|
|
||||||
Any variable can be used in an interface. So how can we use this feature to pass any type of variable to a function?
|
Any variable can be used in an interface. So how can we use this feature to pass any type of variable to a function?
|
||||||
|
|
||||||
For example we use fmt.Println a lot, but have you ever noticed that it can accept any type of argument? Looking at the open source code of fmt, we see the following definition.
|
For example we use `fmt.Println` a lot, but have you ever noticed that it can accept any type of argument? Looking at the open source code of `fmt`, we see the following definition.
|
||||||
```Go
|
```Go
|
||||||
type Stringer interface {
|
type Stringer interface {
|
||||||
String() string
|
String() string
|
||||||
@@ -210,7 +214,7 @@ type Human struct {
|
|||||||
phone string
|
phone string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Human implemented fmt.Stringer
|
// Human implements fmt.Stringer
|
||||||
func (h Human) String() string {
|
func (h Human) String() string {
|
||||||
return "Name:" + h.name + ", Age:" + strconv.Itoa(h.age) + " years, Contact:" + h.phone
|
return "Name:" + h.name + ", Age:" + strconv.Itoa(h.age) + " years, Contact:" + h.phone
|
||||||
}
|
}
|
||||||
@@ -219,8 +223,8 @@ func main() {
|
|||||||
Bob := Human{"Bob", 39, "000-7777-XXX"}
|
Bob := Human{"Bob", 39, "000-7777-XXX"}
|
||||||
fmt.Println("This Human is : ", Bob)
|
fmt.Println("This Human is : ", Bob)
|
||||||
}
|
}
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Looking back to the example of Box, you will find that Color implements interface Stringer as well, so we are able to customize the print format. If we don't implement this interface, fmt.Println prints the type with its default format.
|
Looking back to the example of Box, you will find that Color implements interface Stringer as well, so we are able to customize the print format. If we don't implement this interface, fmt.Println prints the type with its default format.
|
||||||
```Go
|
```Go
|
||||||
fmt.Println("The biggest one is", boxes.BiggestsColor().String())
|
fmt.Println("The biggest one is", boxes.BiggestsColor().String())
|
||||||
@@ -362,7 +366,7 @@ type ReadWriter interface {
|
|||||||
```
|
```
|
||||||
### Reflection
|
### Reflection
|
||||||
|
|
||||||
Reflection in Go is used for determining information at runtime. We use the `reflect` package, and this official [article](http://golang.org/doc/articles/laws_of_reflection.html) explains how reflect works in Go.
|
Reflection in Go is used for determining information at runtime. We use the `reflect` package, and [The Laws of Reflection](http://golang.org/doc/articles/laws_of_reflection.html) post explains how reflect works in Go.
|
||||||
|
|
||||||
There are three steps involved when using reflect. First, we need to convert an interface to reflect types (reflect.Type or reflect.Value, this depends on the situation).
|
There are three steps involved when using reflect. First, we need to convert an interface to reflect types (reflect.Type or reflect.Value, this depends on the situation).
|
||||||
```Go
|
```Go
|
||||||
@@ -372,10 +376,13 @@ v := reflect.ValueOf(i) // get actual value in type i, and use v to change its
|
|||||||
After that, we can convert the reflected types to get the values that we need.
|
After that, we can convert the reflected types to get the values that we need.
|
||||||
```Go
|
```Go
|
||||||
var x float64 = 3.4
|
var x float64 = 3.4
|
||||||
|
|
||||||
|
t := reflect.TypeOf(x)
|
||||||
v := reflect.ValueOf(x)
|
v := reflect.ValueOf(x)
|
||||||
fmt.Println("type:", v.Type())
|
|
||||||
|
fmt.Println("type:", t)
|
||||||
|
fmt.Println("value:", v)
|
||||||
fmt.Println("kind is float64:", v.Kind() == reflect.Float64)
|
fmt.Println("kind is float64:", v.Kind() == reflect.Float64)
|
||||||
fmt.Println("value:", v.Float())
|
|
||||||
```
|
```
|
||||||
Finally, if we want to change the values of the reflected types, we need to make it modifiable. As discussed earlier, there is a difference between pass by value and pass by reference. The following code will not compile.
|
Finally, if we want to change the values of the reflected types, we need to make it modifiable. As discussed earlier, there is a difference between pass by value and pass by reference. The following code will not compile.
|
||||||
```Go
|
```Go
|
||||||
|
|||||||
Reference in New Issue
Block a user