はじめに
オブジェクト指向の考え方などではく、オブジェクト指向型で使用する記法や気になったロジックを書き留めたいと思い記事にしてます。
オブジェクト指向型の記法
その(1)
-
constructメソッド
で値を受け取りクラス内で使える - クラス内のメソッドを呼び出し方
$person = new Person('田中');
$person->greet();
class Person
{
public function __construct(private string $name)
{
}
public function greet()
{
echo 'はじめまして' . $this->name . 'です';
}
}
$tanaka = new Greeting('田中');
$tanaka->greet();
//=>はじめまして田中です
その(2)
- クラス内で新たなクラスをインスタンス化できる
$player = new Player($this->name);
- 新しくインスタンス化したクラスのメソッドを呼び出せる
$kickOff = $player->KickBall();
- constructのプロパティを新しいクラスの引数に取れる
constructの田中をnew Player($this->name);と記述して受け取る
//Playerクラスをインスタンス化するためPlayerクラスが定義されたファイルを読み込んでます
require('Player.php');
class Sports
{
public function __construct(private string $name)
{
}
public function play()
{
//田中がPlayerクラスに渡る
$player = new Player($this->name);
$kickOff = $player->KickBall();
echo $kickOff;
}
}
$sports = new Sports('田中');
$sports->play();
結果
//=>田中がボールを蹴り出しました
class Player
{
public function __construct(private string $name)
{
}
public function kickBall(): string
{
return $this->name . 'がボールを蹴り出しました';
}
}
その(3)~メソッドやプロパティのアクセス権~
public : クラス外や他クラス(別ファイル)からでも使用できる
private : クラス内でしか使用できない
=>修正したいメソッドがpublicだと他クラスで使用していないか確認しないといけなくなる。なので、他で使用しないメソッドに関してはprivateにするのが良い。
playメソッドをpublicからprivate function play()に変更
して、Sportsクラス外から$sports->play();
でメソッドを呼び出すとエラーになる。
<?php
require('Player.php');
class Sports
{
public function __construct(private string $name)
{
}
private function play()
{
$player = new Player($this->name);
$keckOff = $player->KickBall();
echo $keckOff;
}
}
$sports = new Sports('田中');
$sports->play();
//=>Fatal error: Uncaught Error: Call to private method Player::KickBall() from scope Sports
その(4)
const
は以下の2パターンで呼び出すことができますが、PHPドキュメントにはself::で呼び出すと記載されている
$this::SUPPORT_WORD;
self::SUPPORT_WORD;
class Sports
{
private const SUPPORT_WORD = 'がんばれ!';
public function __construct(private string $name)
{
}
public function play()
{
$player = new Player($this->name);
$keckOff = $player->KickBall();
echo $keckOff;
echo $this::SUPPORT_WORD;
}
}
$sports = new Sports('田中');
$sports->play();
その(5)~インスタンスを引数に持つ書き方~
前提:new Category()
の引数にスポーツを入れると、そのスポーツの競技人口が取得できるプログラムです
1枚目:Categoryインスタンスをメソッドの中に書いた場合の記法
2枚目:Categoryインスタンスをメソッドの外に書き引数で受けった場合の記法
class Sports
{
public function CheckPopulation()
{
$category = new Category('baseball');
echo $category->getPopulation();
echo $category->getSportsName();
}
}
$sports = new Sports();
$sports->CheckPopulation();
//=>3千500万
//=>baseball
class Sports
{
public function CheckPopulation(Category $category)
{
echo $category->getPopulation();
echo $category->getSportsName();
}
}
$category = new Category('baseball');
$sports = new Sports();
$sports->CheckPopulation($category);
//Categoryインスタンスを引数に直接とることもできる
//$sports = new Sports();
//$sports->CheckPopulation(new Category('baseball'));
//=>3千500万
//=>baseball
CategoryインスタンスをCheckPopulation()メソッドの引数に取っておけば、そのメソッド内でCategoryインスタンスのメソッド$category->getPopulation()が使用できるようです。
その(6)
複数のインスタンスを生成してもconstructのプロパティは上書きされない。
$baseball = new Category('baseball');
と$soccer = new Category('soccer');
は別のインスタンスでそれぞれ$name
を持っている。
そのため、$baseball
と$soccer
のインスタンス毎のメソッドが実行される。
イメージ
$category($baseball)->getPopulation();
$category($soccer)->getPopulation();
参考:(本)オブジェクト指向でなぜつくるのか / 89p
class Sports
{
public function __construct()
{
}
public function getPopulation(Category $category)
{
echo $category->getPopulation();
}
}
$baseball = new Category('baseball');
$soccer = new Category('soccer');
$categories = [$baseball, $soccer];
foreach ($categories as $category) {
$sports = new Sports();
$sports->getPopulation($category);
}
class Category
{
private const SPORTS_POPULATION = [
'soccer' => '2億6千万',
'baseball' => '3千500万',
];
public function __construct(private string $name)
{
}
public function getPopulation(): string
{
return self::SPORTS_POPULATION[$this->name];
}
}
その(7)継承のコンストラクタ
親と子のコンストラクタの処理は同じでも、わざわざオーバーライドする意味は?
- stackoverflowではオーバーライドしなくても問題ない、ただ暗黙的でないと回答されている。(暗黙的でないことは悪なのかな。。)
https://stackoverflow.com/questions/40244181/is-it-mandatory-to-call-parent-construct-from-the-constructor-of-child-class - PHP公式ドキュメントには
「子クラスでコンストラクタを定義していない場合は、親クラスのコンストラクタを継承します (ただし、private 宣言されている場合は除く)」
と記載されているので子クラスから同じ処理の親コンストラクタを呼び出す必要はなさそう。
https://www.php.net/manual/ja/language.oop5.decon.php
abstract class A
{
public function __construct(protected string $name)
{
}
class B extends A
{
public function __construct(string $name)
{
parent::__construct($name);
}
最後に
公式ドキュメントを参照することで、詳細な情報を得ることができ、より深い理解や技術的な知識を習得できました。
https://www.php.net/manual/ja/oop5.intro.php