improving this chapter
This commit is contained in:
88
en/02.5.md
88
en/02.5.md
@@ -1,6 +1,6 @@
|
|||||||
# Object-oriented
|
# Object-oriented
|
||||||
|
|
||||||
We talked about functions and structs in the last two sections, but did you ever consider using functions as fields of a struct? In this section, I will introduce you to another form of function that has a receiver, which is called `method`.
|
We talked about functions and structs in the last two sections, but did you ever consider using functions as fields of a struct? In this section, I will introduce you to another form of function that has a receiver, which is called a `method`.
|
||||||
|
|
||||||
## method
|
## method
|
||||||
|
|
||||||
@@ -36,9 +36,9 @@ Figure 2.8 Relationship between function and struct
|
|||||||
|
|
||||||
Obviously that's not cool. Also, the area should really be the property of a circle or rectangle.
|
Obviously that's not cool. Also, the area should really be the property of a circle or rectangle.
|
||||||
|
|
||||||
For those reasons, we have the `method` concept. `method` is affiliated with type. It has the same syntax as functions do except for an additional parameter after the `func` keyword called the `receiver`, which is the main body of that method.
|
This is where a `method` comes to play. The `method` is a function affiliated with a type. It has similar syntax as function except, after the `func` keyword has a parameter called the `receiver`, which is the main body of that method.
|
||||||
|
|
||||||
Using the same example, `Rectangle.area()` belongs directly to rectangle, instead of as a peripheral function. More specifically, `length`, `width` and `area()` all belong to rectangle.
|
Using the same example, `Rectangle.Area()` belongs directly to rectangle, instead of as a peripheral function. More specifically, `length`, `width` and `Area()` all belong to rectangle.
|
||||||
|
|
||||||
As Rob Pike said.
|
As Rob Pike said.
|
||||||
|
|
||||||
@@ -57,35 +57,37 @@ import (
|
|||||||
"math"
|
"math"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Rectangle struct {
|
|
||||||
width, height float64
|
|
||||||
}
|
|
||||||
|
|
||||||
type Circle struct {
|
type Circle struct {
|
||||||
radius float64
|
radius float64
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r Rectangle) area() float64 {
|
type Rectangle struct {
|
||||||
return r.width * r.height
|
width, height float64
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c Circle) area() float64 {
|
// method
|
||||||
|
func (c Circle) Area() float64 {
|
||||||
return c.radius * c.radius * math.Pi
|
return c.radius * c.radius * math.Pi
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
// method
|
||||||
r1 := Rectangle{12, 2}
|
func (r Rectangle) Area() float64 {
|
||||||
r2 := Rectangle{9, 4}
|
return r.width * r.height
|
||||||
c1 := Circle{10}
|
|
||||||
c2 := Circle{25}
|
|
||||||
|
|
||||||
fmt.Println("Area of r1 is: ", r1.area())
|
|
||||||
fmt.Println("Area of r2 is: ", r2.area())
|
|
||||||
fmt.Println("Area of c1 is: ", c1.area())
|
|
||||||
fmt.Println("Area of c2 is: ", c2.area())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
c1 := Circle{10}
|
||||||
|
c2 := Circle{25}
|
||||||
|
r1 := Rectangle{9, 4}
|
||||||
|
r2 := Rectangle{12, 2}
|
||||||
|
|
||||||
|
fmt.Println("Area of c1 is: ", c1.Area())
|
||||||
|
fmt.Println("Area of c2 is: ", c2.Area())
|
||||||
|
fmt.Println("Area of r1 is: ", r1.Area())
|
||||||
|
fmt.Println("Area of r2 is: ", r2.Area())
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Notes for using methods.
|
Notes for using methods.
|
||||||
|
|
||||||
- If the name of methods are the same but they don't share the same receivers, they are not the same.
|
- If the name of methods are the same but they don't share the same receivers, they are not the same.
|
||||||
@@ -96,7 +98,7 @@ Notes for using methods.
|
|||||||
|
|
||||||
Figure 2.9 Methods are different in different structs
|
Figure 2.9 Methods are different in different structs
|
||||||
|
|
||||||
In the example above, the area() methods belong to both Rectangle and Circle respectively, so the receivers are Rectangle and Circle.
|
In the example above, the Area() methods belong to both Rectangle and Circle respectively, so the receivers are Rectangle and Circle.
|
||||||
|
|
||||||
One thing that's worth noting is that the method with a dotted line means the receiver is passed by value, not by reference. The difference between them is that a method can change its receiver's values when the receiver is passed by reference, and it gets a copy of the receiver when the receiver is passed by value.
|
One thing that's worth noting is that the method with a dotted line means the receiver is passed by value, not by reference. The difference between them is that a method can change its receiver's values when the receiver is passed by reference, and it gets a copy of the receiver when the receiver is passed by value.
|
||||||
|
|
||||||
@@ -107,11 +109,10 @@ Use the following format to define a customized type.
|
|||||||
type typeName typeLiteral
|
type typeName typeLiteral
|
||||||
```
|
```
|
||||||
Examples of customized types:
|
Examples of customized types:
|
||||||
|
|
||||||
```Go
|
```Go
|
||||||
type ages int
|
type age int
|
||||||
|
|
||||||
type money float32
|
type money float32
|
||||||
|
|
||||||
type months map[string]int
|
type months map[string]int
|
||||||
|
|
||||||
m := months {
|
m := months {
|
||||||
@@ -121,6 +122,7 @@ m := months {
|
|||||||
"December":31,
|
"December":31,
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
I hope that you know how to use customized types now. Similar to `typedef` in C, we use `ages` to substitute `int` in the above example.
|
I hope that you know how to use customized types now. Similar to `typedef` in C, we use `ages` to substitute `int` in the above example.
|
||||||
|
|
||||||
Let's get back to talking about `method`.
|
Let's get back to talking about `method`.
|
||||||
@@ -139,23 +141,24 @@ const (
|
|||||||
YELLOW
|
YELLOW
|
||||||
)
|
)
|
||||||
|
|
||||||
type Color byte
|
|
||||||
|
|
||||||
type Box struct {
|
type Box struct {
|
||||||
width, height, depth float64
|
width, height, depth float64
|
||||||
color Color
|
color Color
|
||||||
}
|
}
|
||||||
|
type Color byte
|
||||||
type BoxList []Box //a slice of boxes
|
type BoxList []Box //a slice of boxes
|
||||||
|
|
||||||
|
// method
|
||||||
func (b Box) Volume() float64 {
|
func (b Box) Volume() float64 {
|
||||||
return b.width * b.height * b.depth
|
return b.width * b.height * b.depth
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// method with a pointer receiver
|
||||||
func (b *Box) SetColor(c Color) {
|
func (b *Box) SetColor(c Color) {
|
||||||
b.color = c
|
b.color = c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// method
|
||||||
func (bl BoxList) BiggestsColor() Color {
|
func (bl BoxList) BiggestsColor() Color {
|
||||||
v := 0.00
|
v := 0.00
|
||||||
k := Color(WHITE)
|
k := Color(WHITE)
|
||||||
@@ -168,12 +171,14 @@ func (bl BoxList) BiggestsColor() Color {
|
|||||||
return k
|
return k
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// method
|
||||||
func (bl BoxList) PaintItBlack() {
|
func (bl BoxList) PaintItBlack() {
|
||||||
for i, _ := range bl {
|
for i, _ := range bl {
|
||||||
bl[i].SetColor(BLACK)
|
bl[i].SetColor(BLACK)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// method
|
||||||
func (c Color) String() string {
|
func (c Color) String() string {
|
||||||
strings := []string{"WHITE", "BLACK", "BLUE", "RED", "YELLOW"}
|
strings := []string{"WHITE", "BLACK", "BLUE", "RED", "YELLOW"}
|
||||||
return strings[c]
|
return strings[c]
|
||||||
@@ -194,14 +199,14 @@ func main() {
|
|||||||
fmt.Println("The color of the last one is", boxes[len(boxes)-1].color.String())
|
fmt.Println("The color of the last one is", boxes[len(boxes)-1].color.String())
|
||||||
fmt.Println("The biggest one is", boxes.BiggestsColor().String())
|
fmt.Println("The biggest one is", boxes.BiggestsColor().String())
|
||||||
|
|
||||||
fmt.Println("Let's paint them all black")
|
// Let's paint them all black
|
||||||
boxes.PaintItBlack()
|
boxes.PaintItBlack()
|
||||||
fmt.Println("The color of the second one is", boxes[1].color.String())
|
|
||||||
|
|
||||||
|
fmt.Println("The color of the second one is", boxes[1].color.String())
|
||||||
fmt.Println("Obviously, now, the biggest one is", boxes.BiggestsColor().String())
|
fmt.Println("Obviously, now, the biggest one is", boxes.BiggestsColor().String())
|
||||||
}
|
}
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
We define some constants and customized types.
|
We define some constants and customized types.
|
||||||
|
|
||||||
- Use `Color` as alias of `byte`.
|
- Use `Color` as alias of `byte`.
|
||||||
@@ -210,11 +215,11 @@ We define some constants and customized types.
|
|||||||
|
|
||||||
Then we defined some methods for our customized types.
|
Then we defined some methods for our customized types.
|
||||||
|
|
||||||
- Volume() uses Box as its receiver and returns the volume of Box.
|
- `Volume()` uses Box as its receiver and returns the volume of Box.
|
||||||
- SetColor(c Color) changes Box's color.
|
- `SetColor(`c Color) changes Box's color.
|
||||||
- BiggestsColor() returns the color which has the biggest volume.
|
- `BiggestsColor()` returns the color which has the biggest volume.
|
||||||
- PaintItBlack() sets color for all Box in BoxList to black.
|
- `PaintItBlack()` sets color for all Box in BoxList to black.
|
||||||
- String() use Color as its receiver, returns the string format of color name.
|
- `String()` use Color as its receiver, returns the string format of color name.
|
||||||
|
|
||||||
Is it much clearer when we use words to describe our requirements? We often write our requirements before we start coding.
|
Is it much clearer when we use words to describe our requirements? We often write our requirements before we start coding.
|
||||||
|
|
||||||
@@ -224,7 +229,7 @@ Let's take a look at `SetColor` method. Its receiver is a pointer of Box. Yes, y
|
|||||||
|
|
||||||
If we see that a receiver is the first argument of a method, it's not hard to understand how it works.
|
If we see that a receiver is the first argument of a method, it's not hard to understand how it works.
|
||||||
|
|
||||||
You might be asking why we aren't using `(*b).Color=c` instead of `b.Color=c` in the SetColor() method. Either one is OK here because Go knows how to interpret the assignment. Do you think Go is more fascinating now?
|
You might be asking why we aren't using `(*b).Color=c` instead of `b.Color=c` in the `SetColor()` method. Either one is OK here because Go knows how to interpret the assignment. Do you think Go is more fascinating now?
|
||||||
|
|
||||||
You may also be asking whether we should use `(&bl[i]).SetColor(BLACK)` in `PaintItBlack` because we pass a pointer to `SetColor`. Again, either one is OK because Go knows how to interpret it!
|
You may also be asking whether we should use `(&bl[i]).SetColor(BLACK)` in `PaintItBlack` because we pass a pointer to `SetColor`. Again, either one is OK because Go knows how to interpret it!
|
||||||
|
|
||||||
@@ -258,13 +263,12 @@ func (h *Human) SayHi() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
mark := Student{Human{"Mark", 25, "222-222-YYYY"}, "MIT"}
|
|
||||||
sam := Employee{Human{"Sam", 45, "111-888-XXXX"}, "Golang Inc"}
|
sam := Employee{Human{"Sam", 45, "111-888-XXXX"}, "Golang Inc"}
|
||||||
|
mark := Student{Human{"Mark", 25, "222-222-YYYY"}, "MIT"}
|
||||||
|
|
||||||
mark.SayHi()
|
|
||||||
sam.SayHi()
|
sam.SayHi()
|
||||||
|
mark.SayHi()
|
||||||
}
|
}
|
||||||
|
|
||||||
```
|
```
|
||||||
### Method overload
|
### Method overload
|
||||||
|
|
||||||
@@ -300,11 +304,11 @@ func (e *Employee) SayHi() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
mark := Student{Human{"Mark", 25, "222-222-YYYY"}, "MIT"}
|
|
||||||
sam := Employee{Human{"Sam", 45, "111-888-XXXX"}, "Golang Inc"}
|
sam := Employee{Human{"Sam", 45, "111-888-XXXX"}, "Golang Inc"}
|
||||||
|
mark := Student{Human{"Mark", 25, "222-222-YYYY"}, "MIT"}
|
||||||
|
|
||||||
mark.SayHi()
|
|
||||||
sam.SayHi()
|
sam.SayHi()
|
||||||
|
mark.SayHi()
|
||||||
}
|
}
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|||||||
Reference in New Issue
Block a user