对于golang
Go语言不支持继承,但支持组合.面向对象语言继承 中的部分功能,可以使用组合 来近似实现.
组合由结构体嵌套结构体来实现.
假设有两个结构体--- 作家author(“父类”)和作品work(“子类”),两结构体字段如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 type author struct { name string nationality string gender string age int work } type work struct { name string category string completedYear int }
author 结构体的字段有name, nationality, gender, age, 同时嵌套一个匿名结构体work 。该字段表明author结构体是由work结构体组合而成。
则现在结构体author可以访问work结构体的所有成员和方法。声明一个work类型的变量w,再声明一个author类型的变量a;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 var w workw.name = "战争与和平" w.category = "masterpiece" w.completedYear = 1869 var a authora.name = "托尔斯泰" a.nationality = "俄国" a.gender = "男" a.age = 82 a.work = w fmt.Printf("作者名为:%s,作品名为:%s" , a.name, a.work.name) fmt.Println("\n" ) fmt.Println(a.category) fmt.Println(a.work.category)
一旦一个结构体嵌套另外一个结构体,Go访问嵌套结构体成员时,就好像是在访问自己结构体成员。也就是说a.work.category可以用a.category来代替。
但当两个结构体都有一个相同字段时,如此处的name,则访问”子结构体”work中的name属性,需要a.work.category,中间的.work不能省却;
上述代码输出:
1 2 3 4 作者名为:战争与和平,作品名为:战争与和平 masterpiece masterpiece
结构体的同名成员(字段)在嵌套时如此,那同名的方法呢?
见如下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 package mainimport "fmt" type author struct { name string nationality string gender string age int work } type work struct { name string category string completedYear int } func (aa author) printSomething() { fmt.Println("我是作家" ) } func (ww work) printSomething() { fmt.Println("我是著作" ) } func (ww work) tellYouSomething() { fmt.Println("作者将“战争”与“和平”的两种生活、两条线索交叉描写,构成一部百科全书式的壮阔史诗。" ) } func main () { var w work w.name = "战争与和平" w.category = "masterpiece" w.completedYear = 1869 var a author a.name = "托尔斯泰" a.nationality = "俄国" a.gender = "男" a.age = 82 a.work = w a.printSomething() a.work.printSomething() a.tellYouSomething() a.work.tellYouSomething() }
输出为:
1 2 3 4 我是作家 我是著作 作者将“战争”与“和平”的两种生活、两条线索交叉描写,构成一部百科全书式的壮阔史诗。 作者将“战争”与“和平”的两种生活、两条线索交叉描写,构成一部百科全书式的壮阔史诗。
可见对方法同样如此.
另注:
golang中的方法和函数与其他编程语言中的同名概念有所不同.官方定义是方法是包含了接收者的函数;
Golang 不是一个纯粹的面向对象的编程语言,它不支持类。因此通过在一个类型上建立方法来实现与 class 相似的行为。
同名方法可以定义在不同的类型上,但是 Golang 不允许同名函数。假设有两个结构体 Square 和 Circle。在 Square 和 Circle 上定义同名的方法是合法的。
更多可点击 ,尤其是其中”值接收者和指针接收者”值得一看
参考 :
Golang 入门 : 结构体(struct)
Golang教程第27节–组合取代继承
golang 组合 继承
对于php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 class author { var $name = "托尔斯泰" ; var $nationality = "俄国" ; var $gender = "男" ; var $age = 82 ; public function printSomething ($one ,$two ) { echo "我是作家\n" ; var_dump ($one ); var_dump ($two ); } public function father ( ) { echo "我是父类中的方法\n" ; } } class work extends author { var $name = "战争与和平" ; var $category = "masterpiece" ; var $completedYear = 1869 ; public function printSomething ($one ,$two ) { echo "我是著作\n" ; var_dump ($one ); return "666" ; } public function children ( ) { echo "我是子类中的方法\n" ; } } $cs = new work ();$cs ->father ();$cs ->children ();$cs ->printSomething ("shuang" ,"hahaha" );echo $cs ->name;echo PHP_EOL;
输出结果为:
1 2 3 4 5 我是父类中的方法 我是子类中的方法 我是著作 string(6) "shuang" 战争与和平
总结
对方法的调用:
$this->方法名();如果子类中有该方法则调用的是子类中的方法,若没有则是调用父类中的;
在子类内部,使用parent::则始终调用的是父类中的方法。
对变量的调用: $this->变量名;如果子类中有该变量则调用的是子类中的,若没有则调用的是父类中的
思考:如上代码中,如何在只实例化子类而不实例化父类的前提下,也不修改和侵入子类代码的情况下,实现调用父类中的(被子类重写的)printSomething()方法?
另注:自PHP5.3之后,子类重写(override)父类方法时(即在子类中重新定义一个和父类中某方法同名的新方法),子类中这个新方法的形参和父类的形参个数必须一致(因为php是弱类型语言,所以对类型是否一致不要求),对返回值无要求;
(如上面代码中,如果class work中的printSomething 方法只有一个参数即printSomething($one),则在运行时会报错:
Warning: Declaration of work::printSomething($one) should be compatible with author::printSomething($one, $two) in /Users/xxxx/xxx/xxx.php on line xx)
对于静态方法,情况类似
参考:
php面向对象的重写与重载
PHP类方法重写原则
php子类中如何调用父类中的变量和方法
php继承父类,子类和父类中都有同名方法,实例化子类,在父类中调用这个方法,调用的是子类的
原文链接: https://dashen.tech/2014/03/01/golang利用组合实现继承-和php或java面向对象的继承有何不同/
版权声明: 转载请注明出处.