Skip to content

Instantly share code, notes, and snippets.

@MilesChou
Last active July 16, 2018 14:41
Show Gist options
  • Save MilesChou/6008841 to your computer and use it in GitHub Desktop.
Save MilesChou/6008841 to your computer and use it in GitHub Desktop.
<?php
/**
* class 教學
*
* class 全域需注意的重點:
* 1.全域:跟function一樣,一經宣告後,任何地方皆可使用。
* 2.不可重載:跟function一樣,一經宣告後,不可再宣告同名的class
*
* 建立class的重點:
* 1.實例化:class宣告後,需使用new建立物件才可使用,$obj = new className();
* 2.屬性(property):可以說是類別的變數,可用 $obj->property 來取得,可以設定預設值,但必需是常數。
* 3.方法(method):可以說是類別的function,可用 $obj->method() 來呼叫。
* 4.偽變量:物件外要取用物件內的屬性或方法時要使用$obj->property或$obj->method(),物件內要取用同一物件內的屬性或方法時要用關鍵字$this->property或$this->method()
* 5.建構方法:__construct()或與類別同名,在使用new的時候會執行的方法。
* 6.建構方法:__destruct(),物件被unset或程式結束時會執行的方法。
* 7.能見度:要設定屬性和方法前可以加上能見度的關鍵字:public任何地方都可以使用,protected父類或子類才可使用,private只有該物件本身才可使用。
* 8.繼承(inheriance):使用extends關鍵字,只能單一繼承。
* 9.覆寫(overriding):子類別可以覆寫父類別的方法。
* 10.final:禁止類別繼承或方法覆寫。
* 11.複製:使用$objB = $objA;時是複製指標,要完整複製一個新的物件要使用clone關鍵字:$objB = clone $objA;
* 12.靜態屬性和方法:屬性和方法前加上static,使用時不需建立物件(new)即可使用
* 類別內呼叫屬性使用self::$property; 呼叫方法使用self::method();
* 類別外呼叫屬性使用className::$property; 呼叫方法使用className::method();
* 13.常數:定義固定值,設定方法:const MESSAGE = 'Hello'; 類別內使用self::MESSAGE;類別外使用className::MESSAGE;
* 14.抽象類:類別加上abstract關鍵字就不能被實例化,必需要被繼承後才能實例化。
* 抽象類中方法被宣告為abstract時,就不需要實作該方法,但被繼承的類別必需要實作該方法
* 15.屬性多載:__get()與__set(), 如果程式呼叫到未定義的屬性時使用
* 16.方法多載:__call(), 如果程式呼叫到未定義的方法時使用
* 17.建構子多載:__clone()搭配clone(deepcopy使用)
* 18.類別多載:如果程式呼叫到未定義的類別時, 會自動執行__autoload()方法
* 19.顯示物件:__toString(), 在類別中實作此方法後, 使用echo或print顯示物件時, 會呼叫__toString()方法
*/
// 懶得加換行語法,做個function自動加
function output($str)
{
return $str . '<br/>';
}
// 宣告class1
class class1
{
// 屬性
public $name;
// 取得name屬性的方法
public function getName()
{
// 使用偽變量來存取屬性
return $this->name;
}
// 設定name屬性的方法
public function setName($var)
{
$this->name = $var;
}
}
// 實例化
$obj = new class1();
// 設定屬性
$obj->name = '我的第一個Class!';
// 呼叫方法
echo output($obj->getName());
class class2
{
// 私有屬性
private $name = '我是class2的預設值';
// 私有屬性外部不能存取 所以必需要有公開方法來存取
public function setName($var)
{
$this->name = $var;
}
public function getName()
{
return $this->name;
}
}
// 實例化
$obj = new class2();
// 預設值
echo output($obj->getName());
// 設定屬性
// $obj2->name = '我的第二個Class!'; >> 這樣會有錯誤 必需使用setName()
$obj->setName('我的第二個Class!');
// 呼叫方法
echo output($obj->getName());
class class3
{
private $name;
// 建構方法
public function __construct($var)
{
// 使用同類別裡的setName方法
$this->setName($var);
}
public function setName($var)
{
$this->name = $var;
}
public function getName()
{
return $this->name;
}
}
// 實例化同時可以執行建構方法
$obj = new class3('我的第三個Class!');
// 並直接輸出
echo output($obj->getName());
class class4
{
private $instance;
private $name = '我是第四個Class哦!';
// 建構方法,參數是物件
public function __construct($instance)
{
$this->instance = $instance;
}
// 取得屬性(物件)的getName方法
public function getInstanceName()
{
return $this->instance->getName();
}
public function setName($var)
{
$this->name = $var;
}
public function getName()
{
return $this->name;
}
}
// 參數為剛剛class3建立的物件
$obj = new class4($obj);
// 輸出class3物件的getName方法
echo output($obj->getInstanceName());
// 輸出class4 getName方法
echo output($obj->getName());
// 進階應用的例子,使用到了設計模式中的工廠模式
class class5
{
private $instances = array();
private $name = '我是第五個Class!';
// 設定實例的方法
public function setInstance($class, $param = 'class5的預設參數')
{
$this->instances[$class] = new $class($param);
}
// 呼叫實例設定名字的方法
public function setInstanceName($class, $var)
{
return $this->instances[$class]->setName($var);
}
// 呼叫實例取得名字的方法
public function getInstanceName($class)
{
return $this->instances[$class]->getName();
}
public function setName($var)
{
$this->name = $var;
}
public function getName()
{
return $this->name;
}
}
$obj = new class5();
$obj->setInstance('class1');
$obj->setInstance('class2');
$obj->setInstance('class3', '被class5建立的class3');
$obj->setInstance('class4');
$obj->setInstance('class5');
$obj->setInstanceName('class1', '被class5設定name的class1');
echo output($obj->getInstanceName('class3'));
echo output($obj->getInstanceName('class1'));
echo output($obj->getInstanceName('class2'));
echo output($obj->getInstanceName('class4'));
echo output($obj->getInstanceName('class5'));
// 跟class1相同 不過改成靜態方法
class class6
{
// 屬性
static public $name;
// 取得name屬性的方法
static public function getName()
{
// 使用偽變量來存取屬性
return self::$name;
}
// 設定name屬性的方法
static public function setName($var)
{
self::$name = $var;
}
}
// $obj = new class1(); >> 不需實例化
// $obj->name = '我的第一個Class!'; >> 設定屬性的方法需要改變
class6::$name = '我的第六個Class!';
// echo output($obj->getName()); >> 呼叫方法也要改變
echo output(class6::getName());
// 繼承(inheriance)
class class7 extends class2
{
private $age;
public function setAge($var)
{
$this->age = $var;
}
public function getAge()
{
return $this->age;
}
// 使用父類別的getName();
public function output()
{
return '我叫' . $this->getName() . ',今年' . $this->getAge() . '歲';
}
}
$obj = new class7();
// 使用父類別的setName();
$obj->setName('QQ');
$obj->setAge(22);
echo output($obj->output());
// 覆寫(overriding)
class class8 extends class7
{
private $height;
public function setHeight($var)
{
$this->height = $var;
}
public function getHeight()
{
return $this->height;
}
// 覆寫顯示的方式,並設定繼承class8的class不可覆寫這個方法
public final function output()
{
return '我今年' . $this->getAge() . '歲,名字叫' . $this->getName() . ',身高' . $this->getHeight();
}
}
$obj = new class8();
$obj->setName('大方');
$obj->setAge(18);
$obj->setHeight(180);
echo output($obj->output());
// 抽象類
abstract class class9
{
private $name;
public function setName($var)
{
$this->name = $var;
}
public function getName()
{
return $this->name;
}
// 宣告抽象類的方法不需實作
abstract public function output();
}
// $obj = new class9(); >> 抽象類不可實例化
// 繼承抽象類class9
class class10 extends class9
{
// 繼承抽象類的類別必需實作抽象類裡的抽象方法
public function output()
{
return '我是class10實作出來的方法,我名字叫"' . $this->getName() .'"';
}
}
$obj = new class10();
$obj->setName('叫我class10');
echo output($obj->output());
// 繼承抽象類class9
class class11 extends class9
{
// 繼承抽象類的類別必需實作抽象類裡的抽象方法
public function output()
{
return '我名字叫"' . $this->getName() . '",我是class11實作出來的方法';
}
}
$obj = new class11();
$obj->setName('class11萬歲');
echo output($obj->output());
// 多載說明太麻煩了跳過
// __toString方法和常數一起講,懶得打程式碼了
class class12
{
//設定常數
const STR = '我的名字叫';
private $name = 'class12';
// 實作後,物件可以直接轉換成字串,會依這個方法回傳值而定
public function __toString()
{
return self::STR . $this->name;
}
public function setName($var)
{
$this->name = $var;
}
public function getName()
{
return $this->name;
}
}
// 常數取用不需實例化
echo output(class12::STR . '大方');
$obj = new class12();
// 直接echo 即可呼叫__toString()方法,或是轉型成string也可呼叫
echo output($obj);
$obj->setName('QQ');
echo output($obj);
// 以下為簡單應用,不過實際上必需還要建立抽象類,然後再繼承去建立每個元素的個別功能,不過我懶了Orz
class element
{
protected $elements = array();
protected $propertys = array();
protected $tag;
public function __construct($tag)
{
$this->tag = $tag;
}
public function __toString()
{
$str = '';
$attbs = '';
foreach($this->elements as $key => $value)
{
$str .= $value. '<br/>';
}
foreach($this->propertys as $key => $value)
{
$attbs .= ' ' . $key . '="' . $value . '"';
}
return '<' . $this->tag . $attbs . '>' . $str . '</' . $this->tag . '>';
}
public function setProperty($key, $value)
{
$this->propertys[$key] = $value;
// return $this 白話意義就是回傳自己,也就是回傳一個物件,而那個物件是自己,所以可以使用像class4那樣連續呼叫一樣
return $this;
}
public function appendElements($tag)
{
$element = new element($tag);
$this->elements[] = $element;
// 需注意的是,一開始有提到直接用等號的話是複製參考,所以這邊$element和$this->elements[]指向的都是同一個物件
return $element;
}
}
$obj = new element('form');
$obj->setProperty('method', 'post')->setProperty('action', 'class.php');
$obj->appendElements('input')->setProperty('value', '輸入A');
$obj->appendElements('input')->setProperty('value', '輸入B');
$obj->appendElements('input')->setProperty('type', 'checkbox');
$obj->appendElements('input')->setProperty('type', 'checkbox')->setProperty('checked', 'checked');
$obj->appendElements('input')->setProperty('type', 'radio')->setProperty('name', 'A');
$obj->appendElements('input')->setProperty('type', 'radio')->setProperty('name', 'A')->setProperty('checked', 'checked');
$obj->appendElements('input')->setProperty('type', 'radio')->setProperty('name', 'B')->setProperty('checked', 'checked');
$obj->appendElements('input')->setProperty('type', 'radio')->setProperty('name', 'B');
$obj->appendElements('textarea');
$obj->appendElements('input')->setProperty('type', 'reset')->setProperty('value', '重新設定');
$obj->appendElements('input')->setProperty('type', 'submit')->setProperty('value', '送出資料');
echo $obj;
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment