博客列表 >php中的类及trait

php中的类及trait

后网络时代
后网络时代原创
2021年03月08日 23:21:221198浏览

1. 实例演示类声明,类的实例化,类的静态成员与类的扩展;

  1. <?php
  2. // 简单类定义
  3. class test{
  4. // 声明属性
  5. public $name=1000;
  6. //构造函数:用户对象初始化
  7. public function __construct($name){
  8. $this->name=$name;
  9. }
  10. //实例方法定义
  11. function demo(){
  12. echo $this->name;
  13. }
  14. }
  15. // //简单类的实例化:
  16. // 要创建一个类的实例,必须使用 new 关键字
  17. $ob=new test('zhangsan');
  18. $ob->demo();
  19. echo "<hr>";
  20. $str="test";
  21. $obj1=new test('张三');
  22. $obj1->demo();
  23. echo "<br>";
  24. // 在类定义内部,可以用 new self 和 new parent 和 new self创建新对象。
  25. // 创建新对象
  26. class AA{
  27. static public function getobj(){
  28. return new AA;//与new self 一致
  29. }
  30. }
  31. class childclass extends AA{}
  32. $obj1=new AA;
  33. $obj2=new $obj1;//产生新对象
  34. var_dump($obj2==$obj1);
  35. echo "<br>";
  36. $obj3=AA::getobj();
  37. var_dump($obj3 instanceof AA);
  38. echo "<br>";
  39. $obj4=childclass::getobj();
  40. var_dump($obj4 instanceof childclass);
  41. echo "<hr>";
  42. class AAA{
  43. static public function getobj(){
  44. return new static;//后期静态绑定开始
  45. }
  46. }
  47. class childclass1 extends AAA{}
  48. $obj5=childclass1::getobj();
  49. var_dump($obj5 instanceof childclass1);
  50. $obj6=&$obj5;
  51. echo "<br>";
  52. var_dump($obj6===$obj5);
  53. echo "<br>";
  54. //动态创建一个
  55. class vary{
  56. public $name="zhangsan";
  57. const st=<<< EOT
  58. 类常量
  59. EOT;//只能字面量
  60. }
  61. echo vary::st;
  62. echo "<br>";
  63. //动态创建对象
  64. $o="vary";
  65. $obj=new $o;
  66. echo $obj->name;
  67. echo "<hr>";
  68. // 静态(static)关键字
  69. // 声明类属性或方法为静态,就可以不实例化类而直接访问
  70. // 静态属性不能通过一个类已实例化的对象来访问(但静态方法可以)。
  71. // 由于静态方法不需要通过对象即可调用,所以伪变量 $this 在静态方法中不可用。
  72. //静态变量是共享的
  73. class foostatic{
  74. public static $my_static="foostatic";//不能被实例调用
  75. public function callstatic(){
  76. echo static::$my_static;
  77. }
  78. public static function callstamothod(){
  79. echo '静态方法可以被对象调用(静态属性不可以由对象通过 -> 操作符来访问。),也可以被类调用,所以在他里面不能使用$this';
  80. }
  81. }
  82. $op=new foostatic;
  83. $op->callstamothod();
  84. echo "<br>";
  85. $op->callstatic();
  86. echo "<br>",foostatic::$my_static;
  87. class Foo {
  88. public static $bar = 'a static property';
  89. }
  90. echo "<br>";
  91. //php 可以使用new 对象名称来生成一个新对象 对象可以使用::来访问静态属性和方法 对象可以当成类来使用,反过来却不行
  92. $baz = (new Foo)::$bar;
  93. echo $baz;
  94. echo "<hr>";
  95. //类的继承 exstends
  96. class ad{
  97. static $id=1;
  98. static public function st(){
  99. echo "static 与public 书写上不讲究";
  100. }
  101. }
  102. class ef extends ad{
  103. static $id=30;//可以重写
  104. static public function st(){ //静态方法可以重写
  105. echo "静态方法可以重写";
  106. }
  107. }
  108. echo ef::$id;//静态属性可以继承
  109. echo "<br>";
  110. echo ef::st();

结果:

2. 描述trait功能,以及trait与父类的区别与联系,并实例演示trait 的冲突与优先级的解决方案

答:

  1. // 为了对使用的类施加强制要求,trait 支持抽象方法的使用。
  2. // 警告
  3. // 一个可继承实体类,可以通过定义同名非抽象方法来满足要求;方法的签名可以不同。
  4. trait Hello {
  5. public function sayHelloWorld() {
  6. echo 'Hello'.$this->getWorld();
  7. }
  8. abstract public function getWorld();
  9. }
  10. class MyHelloWorld {
  11. private $world=111;
  12. use Hello;
  13. public function getWorld() {
  14. return $this->world;
  15. }
  16. public function setWorld($val) {
  17. $this->world = $val;
  18. }
  19. }
  20. $obj=new MyHelloWorld();
  21. echo $obj->getWorld();
  22. echo "<hr>";
  23. // Traits 可以定义静态成员静态方法静态变量。
  24. trait counter{
  25. public static $name="zhangsan";
  26. public function inc(){
  27. static $c=0;
  28. $c=$c+1;
  29. echo "$c\n";
  30. }
  31. public static function de(){
  32. echo "静态方法!!";
  33. }
  34. }
  35. class c1{
  36. use counter;
  37. }
  38. class c2{
  39. use counter;
  40. }
  41. $o=new c1();
  42. $o->inc();
  43. $p=new c2();
  44. $p->inc();
  45. echo "<br>";
  46. $p->de();
  47. c1::de();
  48. echo "<br>";
  49. echo c1::$name;
  50. echo "<hr>";
  51. // Trait 定义了一个属性后,类就不能定义同样名称的属性,否则会产生 fatal error。
  52. // 有种情况例外:属性是兼容的(同样的访问可见度、初始默认值)。
  53. // 在 PHP 7.0 之前,属性是兼容的,则会有 E_STRICT 的提醒。
  54. //优先顺序示例
  55. // 从基类继承的成员会被Trait中的同名成员覆盖。
  56. // 优先顺序是当前类中的方法会覆盖 trait 方法,
  57. // 而 trait 方法又覆盖了基类中的方法。
  58. //属性定义的时候只能定义成
  59. // class demoT{
  60. // public $name=111;
  61. // }
  62. // trait tt{
  63. // public $name=111;
  64. // }
  65. // class yy extends demoT{
  66. // use tt;
  67. // public $name=222;
  68. // }
  69. class Base{
  70. public function hello(){
  71. echo "helloword (parent)";
  72. }
  73. }
  74. trait sayWorld{
  75. function hello(){
  76. parent::hello();
  77. echo "<br>";
  78. echo "trait,覆盖了父类的同名方法";
  79. }
  80. }
  81. class parentandtrait extends Base{
  82. use sayworld;
  83. }
  84. $obj=new parentandtrait;
  85. $obj->hello();
  86. echo "<br>";
  87. class Mythod{
  88. use sayworld;
  89. public function hello(){
  90. echo "当前类型中与trait中同名的方法会覆盖trait中的方法";
  91. }
  92. }
  93. $obj1=new Mythod;
  94. $obj1->hello();
  95. //总结:优先顺序是当前类中的方法会覆盖 trait 方法,而 trait 方法又覆盖了基类中的方法
  96. echo "<hr>";
  97. //多个 trait
  98. // 通过逗号分隔,在 use 声明列出多个 trait,可以都插入到一个类中。
  99. trait arr1{
  100. public function member(){
  101. echo "会员数据信息";
  102. echo "<pre></pre>";
  103. }
  104. }
  105. trait arr2{
  106. public function mark(){
  107. echo "会员积分";
  108. echo "<pre></pre>";
  109. }
  110. }
  111. class currentclass{
  112. use arr1,arr2;
  113. public function output(){
  114. echo "对个trait的使用";
  115. echo "<pre></pre>";
  116. }
  117. }
  118. $obj=new currentclass;
  119. $obj->output();
  120. $obj->member();
  121. $obj->mark();
  122. echo "<hr>";
  123. // 如果两个 trait 都插入了一个同名的方法,如果没有明确解决冲突将会产生一个致命错误。
  124. // 为了解决多个 trait 在同一个类中的命名冲突,
  125. // 需要使用 insteadof 操作符来明确指定使用冲突方法中的哪一个。
  126. // 以上方式仅允许排除掉其它方法,as 操作符可以 为某个方法引入别名。
  127. // 注意,as 操作符不会对方法进行重命名,也不会影响其方法。
  128. trait AAA{
  129. public function smallTalk(){
  130. echo 'a';
  131. }
  132. public function bigTalk(){
  133. echo "A";
  134. }
  135. }
  136. trait BBB{
  137. public function smallTalk(){
  138. echo 'b';
  139. }
  140. public function bigTalk(){
  141. echo "B";
  142. }
  143. }
  144. class Talker{
  145. use AAA,BBB{
  146. BBB::smallTalk insteadof AAA;
  147. AAA::bigTalk insteadof BBB;
  148. }
  149. }
  150. $obj=new Talker;
  151. $obj->smallTalk();
  152. echo "<br>";
  153. $obj->bigTalk();
  154. echo "<hr>";
  155. class aliased_as{
  156. use AAA,BBB{
  157. BBB::smallTalk insteadof AAA;
  158. AAA::bigTalk insteadof BBB;
  159. BBB::bigTalk as aliased_BBB;
  160. }
  161. }
  162. $obj=new aliased_as;
  163. $obj->aliased_BBB();
  164. echo "<pre></pre>";
  165. // 修改方法的访问控制,使用 as 语法还可以用来调整方法的访问控制。
  166. //示例 #6 修改方法的访问控制
  167. trait modfy_as{
  168. public function hello(){
  169. echo "使用as修改权限";
  170. }
  171. }
  172. class modfyasclass{
  173. use modfy_as{
  174. hello as protected;
  175. }
  176. function test(){
  177. echo $this->hello();
  178. }
  179. }
  180. $obj=new modfyasclass;
  181. // $obj->hello();
  182. $obj->test();
  183. // 给方法一个改变了访问控制的别名
  184. // 原版 sayHello 的访问控制则没有发生变化
  185. class modfyasclassii{
  186. use modfy_as{
  187. hello as protected okay;
  188. }
  189. function test(){
  190. $this->okay();
  191. }
  192. }
  193. $obj=new modfyasclassii;
  194. $obj->test();
  195. echo "<hr>";
  196. // 从 trait 来组成 trait
  197. // 正如 class 能够使用 trait 一样,其它 trait 也能够使用 trait。
  198. // 在 trait 定义时通过使用一个或多个 trait,
  199. // 能够组合其它 trait 中的部分或全部成员。
  200. trait okay{
  201. public function Testokay(){
  202. echo "Testokay";
  203. }
  204. }
  205. trait Methodtest{
  206. public function Testmethod(){
  207. echo "Methodtest";
  208. }
  209. }
  210. trait testokaymethod{
  211. use okay,Methodtest;
  212. }
  213. class okay_methodtest{
  214. use testokaymethod;
  215. }
  216. $obj=new okay_methodtest;
  217. $obj->Testokay();
  218. echo "<pre></pre>";
  219. $obj->Testmethod();
  220. echo "<br>";

运行结果:

声明:本文内容转载自脚本之家,由网友自发贡献,版权归原作者所有,如您发现涉嫌抄袭侵权,请联系admin@php.cn 核实处理。
全部评论
文明上网理性发言,请遵守新闻评论服务协议