golang面向对象分析 (2)

因为匿名组合不提供多态的特性. 如下面的代码:

package main type A struct{ } type B struct { A //B is-a A } func save(A) { //do something } func main() { b := new(B) save(*b); }

Output

cannot use *b (type B) as type A in argument to save

完整代码

还有一个面试题的例子

type People struct{} func (p *People) ShowA() { fmt.Println("showA") p.ShowB() } func (p *People) ShowB() { fmt.Println("showB") } type Teacher struct { People } func (t *Teacher) ShowB() { fmt.Println("teacher showB") } func main() { t := Teacher{} t.ShowA() }

输出结果是什么呢?

Output

ShowA ShowB

Effective Go Says:

There's an important way in which embedding differs from subclassing. When we embed a type, the methods of that type become methods of the outer type, but when they are invoked the receiver of the method is the inner type, not the outer one

也就是说, Teacher由于组合了People, 所以Teacher也有了ShowA()方法, 但是在ShowA()方法里执行到ShowB时, 这个时候的receiver是*People而不是*Teacher, 主要原因还是因为embedding是一个Pseudo is-a, 没有多态的功能.

4、 "多继承"的问题

package main import "fmt" type School struct { address string } func (s *School) Address() { fmt.Println("School Address:", s.address) } type Home struct { address string } func (h *Home) Address() { fmt.Println("Home Address:", h.address) } type Student struct { School Home name string } func main() { mark := Student{School{"aaa"}, Home{"bbbb"}, "cccc"} fmt.Println(mark) mark.Address() fmt.Println(mark.address) mark.Home.Address() fmt.Println(mark.Home.address) }

输出结果:

30: ambiguous selector mark.Address 31: ambiguous selector mark.address

完整代码

由此可以看出, Golang中不管是方法还是属性都不存在类似C++那样的多继承的问题. 要访问Embedding相关的属性和方法, 需要在加那个相应的匿名字段, 如:

mark.Home.Address()

5、Embedding value和 Embedding pointer的区别

package main import ( "fmt" ) type Person struct { name string } type Student struct { *Person age int } type Teacher struct { Person age int } func main() { s := Student{&Person{"student"}, 10} t := Teacher{Person{"teacher"}, 40} fmt.Println(s, s.name) fmt.Println(t, t.name) }

Output

{0x1040c108 10} student {{teacher} 40} teacher

完整代码

I. 两者对于结果来说, 没有啥区别, 只是对传参的时候有影响
II. Embedding value是比较常规的写法
III. Embedding pointer比较有优势一点, 不需要关注指针是什么时间被初始化的.

三. Interface

Golang中Composite不提供多态的功能, 那是否Golang不提供多态呢? 答案肯定是否定. Golang依靠Interface实现多态的功能.

下面是我工程里面一段代码的简化:

package main import ( "fmt" ) type Check interface { CheckOss() } type CheckAudio struct { //something } func (c *CheckAudio) CheckOss() { fmt.Println("CheckAudio do CheckOss") } func main() { checkAudio := CheckAudio{} var i Check i = &checkAudio //想一下这里为啥需要& i.CheckOss() }

完整代码

1、Interface 如何Composite ?

type Reader interface { Read(p []byte) (n int, err error) } type Writer interface { Write(p []byte) (n int, err error) } type ReadWriter interface { Reader Writer }

其实很简单, 就是把Reader, Writer嵌入到ReadWriter中, 这样ReadWriter就拥有了Reader和Writer的方法.

尾声

至此, 基本说完了Golang的面向对象. 有哪里我理解的不对的地方, 请给我留言.

参考资料

Go面试题

Is Go An Object Oriented Language?

go web编程

object-oriented-programming-in-go

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wssfps.html