Correcting teacher:天蓬老师
Correction status:qualified
Teacher's comments:
<?php
// 简单类定义
class test{
// 声明属性
public $name=1000;
//构造函数:用户对象初始化
public function __construct($name){
$this->name=$name;
}
//实例方法定义
function demo(){
echo $this->name;
}
}
// //简单类的实例化:
// 要创建一个类的实例,必须使用 new 关键字
$ob=new test('zhangsan');
$ob->demo();
echo "<hr>";
$str="test";
$obj1=new test('张三');
$obj1->demo();
echo "<br>";
// 在类定义内部,可以用 new self 和 new parent 和 new self创建新对象。
// 创建新对象
class AA{
static public function getobj(){
return new AA;//与new self 一致
}
}
class childclass extends AA{}
$obj1=new AA;
$obj2=new $obj1;//产生新对象
var_dump($obj2==$obj1);
echo "<br>";
$obj3=AA::getobj();
var_dump($obj3 instanceof AA);
echo "<br>";
$obj4=childclass::getobj();
var_dump($obj4 instanceof childclass);
echo "<hr>";
class AAA{
static public function getobj(){
return new static;//后期静态绑定开始
}
}
class childclass1 extends AAA{}
$obj5=childclass1::getobj();
var_dump($obj5 instanceof childclass1);
$obj6=&$obj5;
echo "<br>";
var_dump($obj6===$obj5);
echo "<br>";
//动态创建一个
class vary{
public $name="zhangsan";
const st=<<< EOT
类常量
EOT;//只能字面量
}
echo vary::st;
echo "<br>";
//动态创建对象
$o="vary";
$obj=new $o;
echo $obj->name;
echo "<hr>";
// 静态(static)关键字
// 声明类属性或方法为静态,就可以不实例化类而直接访问
// 静态属性不能通过一个类已实例化的对象来访问(但静态方法可以)。
// 由于静态方法不需要通过对象即可调用,所以伪变量 $this 在静态方法中不可用。
//静态变量是共享的
class foostatic{
public static $my_static="foostatic";//不能被实例调用
public function callstatic(){
echo static::$my_static;
}
public static function callstamothod(){
echo '静态方法可以被对象调用(静态属性不可以由对象通过 -> 操作符来访问。),也可以被类调用,所以在他里面不能使用$this';
}
}
$op=new foostatic;
$op->callstamothod();
echo "<br>";
$op->callstatic();
echo "<br>",foostatic::$my_static;
class Foo {
public static $bar = 'a static property';
}
echo "<br>";
//php 可以使用new 对象名称来生成一个新对象 对象可以使用::来访问静态属性和方法 对象可以当成类来使用,反过来却不行
$baz = (new Foo)::$bar;
echo $baz;
echo "<hr>";
//类的继承 exstends
class ad{
static $id=1;
static public function st(){
echo "static 与public 书写上不讲究";
}
}
class ef extends ad{
static $id=30;//可以重写
static public function st(){ //静态方法可以重写
echo "静态方法可以重写";
}
}
echo ef::$id;//静态属性可以继承
echo "<br>";
echo ef::st();
结果:
答:
// 为了对使用的类施加强制要求,trait 支持抽象方法的使用。
// 警告
// 一个可继承实体类,可以通过定义同名非抽象方法来满足要求;方法的签名可以不同。
trait Hello {
public function sayHelloWorld() {
echo 'Hello'.$this->getWorld();
}
abstract public function getWorld();
}
class MyHelloWorld {
private $world=111;
use Hello;
public function getWorld() {
return $this->world;
}
public function setWorld($val) {
$this->world = $val;
}
}
$obj=new MyHelloWorld();
echo $obj->getWorld();
echo "<hr>";
// Traits 可以定义静态成员静态方法静态变量。
trait counter{
public static $name="zhangsan";
public function inc(){
static $c=0;
$c=$c+1;
echo "$c\n";
}
public static function de(){
echo "静态方法!!";
}
}
class c1{
use counter;
}
class c2{
use counter;
}
$o=new c1();
$o->inc();
$p=new c2();
$p->inc();
echo "<br>";
$p->de();
c1::de();
echo "<br>";
echo c1::$name;
echo "<hr>";
// Trait 定义了一个属性后,类就不能定义同样名称的属性,否则会产生 fatal error。
// 有种情况例外:属性是兼容的(同样的访问可见度、初始默认值)。
// 在 PHP 7.0 之前,属性是兼容的,则会有 E_STRICT 的提醒。
//优先顺序示例
// 从基类继承的成员会被Trait中的同名成员覆盖。
// 优先顺序是当前类中的方法会覆盖 trait 方法,
// 而 trait 方法又覆盖了基类中的方法。
//属性定义的时候只能定义成
// class demoT{
// public $name=111;
// }
// trait tt{
// public $name=111;
// }
// class yy extends demoT{
// use tt;
// public $name=222;
// }
class Base{
public function hello(){
echo "helloword (parent)";
}
}
trait sayWorld{
function hello(){
parent::hello();
echo "<br>";
echo "trait,覆盖了父类的同名方法";
}
}
class parentandtrait extends Base{
use sayworld;
}
$obj=new parentandtrait;
$obj->hello();
echo "<br>";
class Mythod{
use sayworld;
public function hello(){
echo "当前类型中与trait中同名的方法会覆盖trait中的方法";
}
}
$obj1=new Mythod;
$obj1->hello();
//总结:优先顺序是当前类中的方法会覆盖 trait 方法,而 trait 方法又覆盖了基类中的方法
echo "<hr>";
//多个 trait
// 通过逗号分隔,在 use 声明列出多个 trait,可以都插入到一个类中。
trait arr1{
public function member(){
echo "会员数据信息";
echo "<pre></pre>";
}
}
trait arr2{
public function mark(){
echo "会员积分";
echo "<pre></pre>";
}
}
class currentclass{
use arr1,arr2;
public function output(){
echo "对个trait的使用";
echo "<pre></pre>";
}
}
$obj=new currentclass;
$obj->output();
$obj->member();
$obj->mark();
echo "<hr>";
// 如果两个 trait 都插入了一个同名的方法,如果没有明确解决冲突将会产生一个致命错误。
// 为了解决多个 trait 在同一个类中的命名冲突,
// 需要使用 insteadof 操作符来明确指定使用冲突方法中的哪一个。
// 以上方式仅允许排除掉其它方法,as 操作符可以 为某个方法引入别名。
// 注意,as 操作符不会对方法进行重命名,也不会影响其方法。
trait AAA{
public function smallTalk(){
echo 'a';
}
public function bigTalk(){
echo "A";
}
}
trait BBB{
public function smallTalk(){
echo 'b';
}
public function bigTalk(){
echo "B";
}
}
class Talker{
use AAA,BBB{
BBB::smallTalk insteadof AAA;
AAA::bigTalk insteadof BBB;
}
}
$obj=new Talker;
$obj->smallTalk();
echo "<br>";
$obj->bigTalk();
echo "<hr>";
class aliased_as{
use AAA,BBB{
BBB::smallTalk insteadof AAA;
AAA::bigTalk insteadof BBB;
BBB::bigTalk as aliased_BBB;
}
}
$obj=new aliased_as;
$obj->aliased_BBB();
echo "<pre></pre>";
// 修改方法的访问控制,使用 as 语法还可以用来调整方法的访问控制。
//示例 #6 修改方法的访问控制
trait modfy_as{
public function hello(){
echo "使用as修改权限";
}
}
class modfyasclass{
use modfy_as{
hello as protected;
}
function test(){
echo $this->hello();
}
}
$obj=new modfyasclass;
// $obj->hello();
$obj->test();
// 给方法一个改变了访问控制的别名
// 原版 sayHello 的访问控制则没有发生变化
class modfyasclassii{
use modfy_as{
hello as protected okay;
}
function test(){
$this->okay();
}
}
$obj=new modfyasclassii;
$obj->test();
echo "<hr>";
// 从 trait 来组成 trait
// 正如 class 能够使用 trait 一样,其它 trait 也能够使用 trait。
// 在 trait 定义时通过使用一个或多个 trait,
// 能够组合其它 trait 中的部分或全部成员。
trait okay{
public function Testokay(){
echo "Testokay";
}
}
trait Methodtest{
public function Testmethod(){
echo "Methodtest";
}
}
trait testokaymethod{
use okay,Methodtest;
}
class okay_methodtest{
use testokaymethod;
}
$obj=new okay_methodtest;
$obj->Testokay();
echo "<pre></pre>";
$obj->Testmethod();
echo "<br>";
运行结果: