大家还是直接看代码吧~
- package main
- import (
- "fmt"
- )
- func main() {
- start(NewB(C{}))
- start(NewB(D{}))
- }
- type A interface {
- what()
- }
- type B struct {
- A
- }
- type C struct {
- }
- func (b C) what() {
- fmt.Println("this is type C")
- }
- type D struct {
- }
- func (b D) what() {
- fmt.Println("this is type D")
- }
- func start(b B) {
- b.what()
- }
- func NewB(a A) B {
- return B{a}
- }
复制代码 补充:【玩转Golang】通过组合嵌入实现代码复用
应用开发中的一个常见情景,为了避免简单重复,需要在基类中实现共用代码,着同样有助于后期维护。
如果在以往的支持类继承的语言中,比如c++,Java,c#等,这很简单!可是go不支持继承,只能mixin嵌入
且看下面的代码:
- type ManKind interface{
- Say(s string);
- GetMouth()string
- }
- type Man struct{
-
- }
- func NewMan() ManKind{
- return &Man{};
- }
- func (this *Man)GetMouth()string{
- return "M0"
- }
- func (this *Man) Say(s string){
- fmt.Printf("\n Speak with mouth[%s] : "%s"",this.GetMouth(),s);
- }
- type StrongMan struct{
- Man
- }
- func NewStrongMan()ManKind{
- return &StrongMan{}
- }
- func (this*StrongMan)GetMouth()string{
- return "M1"
- }
- func main(){
- NewMan().Say("good luck!")
- NewStrongMan().Say("good luck!")
- }
复制代码如果支持继承,很明显应该输出 - Speak with mouth[M0] : "good luck!"
- Speak with mouth[M1] : "good luck!"
复制代码但是在golang中只能输出: - Speak with mouth[M0] : "good luck!"
- Speak with mouth[M0] : "good luck!"
复制代码StrongMan中调用Say(),此时可以将指针传递到内嵌类,只是简单的指向了Man的方法,在ManKind中调用GetMouth就是ManKind自己的GetMouth,和StrongMan没有关系。
当然,我们可以在StrongMan中覆盖Say方法
- func (this *StrongMan)Say(s string){
- fmt.Printf("\n Speak with mouth[%s] : "%s"",this.GetMouth(),s);
- }
复制代码此时,当然可以正确输出,因为本来调用的就都是StrongMan自己的方法了,这又和我们的初衷相违背了。那么这种情况怎么实现呢?我的方法是,让Man再脏一点儿,把需要的东西传递给组合进来的类。
给Man增加一个属性mouth,增加一个SetMouth方法,修改一下GetMouth方法,StrongMan的GetMouth方法删除掉,再修改一下NewStrongMan方法
最后的代码如下:
- package main
- import(
- "fmt"
- )
- type ManKind interface{
- Say(s string);
- SetMouth(m string)
- GetMouth()string
- }
- type Man struct{
- ManKind
- mouth string
- }
- func NewMan() ManKind{
- return &Man{mouth:"M0"};
- }
- func (this *Man)GetMouth()string{
- return this.mouth;
- }
- func (this *Man)SetMouth(s string){
- this.mouth=s;
- }
- func (this *Man) Say(s string){
- fmt.Printf("\n Speak with mouth[%s] : "%s"",this.GetMouth(),s);
- }
- type StrongMan struct{
- Man
- }
- func NewStrongMan()ManKind{
- sm := &StrongMan{}
- sm.SetMouth("M1");
- return sm;
- }
-
- func main(){
- NewMan().Say("good luck!")
- &NewStrongMan().Say("good luck!")
- }
复制代码当然,如果你不愿意用Get、Set方法,也可以直接输出Man的Mouth属性。
我总结的嵌入式编程要点:
1,被嵌入的类的方法,只能访问他自己的字段,包装类即时声明了同名字段也没用。
2,包装类可以覆盖嵌入类的方法,但是嵌入类访问不到,亦然访问自己的方法。只能在包装类中连同调用方法一同实现。
3,包装类覆盖嵌入类字段后,亦然可以通过嵌入类的类名访问嵌入类的字段。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持晓枫资讯。如有错误或未考虑完全的地方,望不吝赐教。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |