// 面向对象
// Go语言根本就不支持面向对象思想中的继承语法
// 1. 为类型添加方法
package main
import "fmt"
type Interger int
// 成员方法,传入Integer 而非*Intege
func (a Interger) Add1(b Interger) {
a += b
}
// 指针引用,修改对象的值
func (a *Interger) Add2(b Interger) {
*a += b
}
func main() {
var a Interger = 1
a.Add1(2)
fmt.Println(a) // ===> 1
a = 1
a.Add2(2)
fmt.Println(a) // ===> 3
}
// 2.值语义和引用语义
// b=a
// b.Modify()
// 如果b的修改不会影响a的值,那么此类型属于值类型。如果会影响a的值,那么此类型是引用 类型。
package main
import "fmt"
func main() {
// Go语言中的数组和基本类型没有区别,是很纯粹的值类型,例如:
var a = [3]int{1, 2, 3}
var b = a
b[1]++
fmt.Println(a, b)
// [1 2 3] [1 2 3]
// 要想表达引用,需要用指针:
var a1 = [3]int{1, 2, 3}
var b1 = &a1
b1[1]++
fmt.Println(a1, *b1)
// [1 3 3] [1 3 3]
// 这表明b=&a赋值语句是数组内容的引用,变量b的类型不是[3]int,而是*[3]int类型。
}
package main
import "fmt"
// 结构体
// Go语言的结构体(struct)和其他语言的类(class)有同等的地位,
// 但Go语言放弃了包括继 承在内的大量面向对象特性,只保留了组合(composition)这个最基础的特性
type Rect struct {
x, y float64
width, height float64
}
func (r *Rect) Area() float64 {
return r.width * r.height
}
func NewRect(x, y, width, height float64) *Rect {
return &Rect{x, y, width, height}
}
func main() {
// 四种创建对象并初始化的方法
rect1 := new(Rect)
rect2 := &Rect{}
rect3 := &Rect{0, 0, 100, 200}
rect4 := &Rect{width: 100, height: 200}
fmt.Println(rect1.Area())
fmt.Println(rect2.Area())
fmt.Println(rect3.Area())
fmt.Println(rect4.Area())
rect5 := NewRect(1, 2, 3, 4)
fmt.Println(rect5.Area())
}
package main
import "fmt"
type person struct {
Name string
Age int
}
type person1 struct {
Name string
Age int
// 嵌套匿名结构
Contact struct {
Phone, City string
}
}
func B(per *person) {
per.Age = 15
fmt.Println("B", per)
}
func C(per *person) {
per.Age = 11
fmt.Println("C", per)
}
func main() {
p := &person{Name: "tom", Age: 19}
p.Name = "Chenc"
fmt.Println(p)
B(p)
C(p)
fmt.Println(p)
a := &struct {
Name string
Age int
}{
Name: "chenc",
Age: 23,
}
fmt.Println(a)
a1 := person1{Name: "tom", Age: 19}
a1.Contact.Phone = "1590232124"
a1.Contact.City = "beijing"
fmt.Println(a1)
}
package main
import "fmt"
// 匿名组合
// 确切地说,Go语言也提供了继承,但是采用了组合的文法,所以我们将其称为匿名组合
// 以上代码定义了一个Base类(实现了Foo()和Bar()两个成员方法),然后定义了一个 Foo类,
// 该类从Base类“继承”并改写了Bar()方法(该方法实现时先调用了基类的Bar() 方法)。
// 在“派生类”Foo没有改写“基类”Base的成员方法时,相应的方法就被“继承”,
// 例如在 上面的例子中,调用foo.Foo()和调用foo.Base.Foo()效果一致。
type human struct {
Sex int
}
type student struct {
human
Name string
Age int
}
type teacher struct {
human
Name string
Age int
}
func main() {
a := teacher{Name: "zhang", Age: 35, human: human{Sex: 0}}
b := student{Name: "li", Age: 18, human: human{Sex: 1}}
a.Name = "zhang_sr"
a.Age = 36
a.Sex = 1
fmt.Println(a, b)
}
package main
import "fmt"
type A struct {
B
Name string
}
type B struct {
Name string
}
func main() {
a := A{Name: "A", B: B{Name: "B"}}
fmt.Println(a.Name, a.B.Name) // A B
//假设A中没有Name属性,只嵌套了B,那么在取a.Name的时候,会向嵌套的结构体中查找
// a := A{B: B{Name: "B"}}
// fmt.Println(a.Name, a.B.Name) // B B
}
// 方法
package main
import "fmt"
type A struct {
B
Name string
}
type B struct {
Name string
}
func (a A) Println() {
a.Name = "lisi"
fmt.Println("A")
}
func (b *B) Println() {
b.Name = "lisi"
fmt.Println("A")
}
func main() {
a := A{Name: "A", B: B{Name: "B"}}
a.Println()
fmt.Println(a)
b := A{Name: "hello", B: B{Name: "go"}}
b.Println()
fmt.Println(b)
}
package main
import "fmt"
type TZ int
func (tz *TZ) Print() {
fmt.Println("tz")
}
func main() {
var a TZ
//Method Value
a.Print() // ===> "tz"
//Method Expression
(*TZ).Print(&a) // ===> "tz"
}