PHPのオブジェクト指向構文まとめ|初級試験(第10章)の頻出ポイント
オブジェクト指向構文(第10章)は、公式の出題比率が17.5%(40問中約7問)と PHP8技術者認定初級試験で最も配点の大きい分野です (章別の出題比率はこちら)。 クラスの定義からコンストラクタ、アクセス修飾子、継承、インターフェイスまで論点は幅広いものの、 問われるのは基本構文の正確な理解です。この記事で頻出ポイントを一気に整理しましょう。
クラスの定義とインスタンス化
クラスはclassキーワードで定義し、newでインスタンス化します。
プロパティやメソッドには->(アロー演算子)でアクセスし、
クラス内部では$thisが自分自身のインスタンスを指します。
class Product
{
public string $name;
private int $price = 0;
public function __construct(string $name, int $price)
{
$this->name = $name;
$this->price = $price;
}
public function getPrice(): int
{
return $this->price;
}
}
$product = new Product('りんご', 150);
echo $product->name; // りんご
echo $product->getPrice(); // 150
コンストラクタプロモーション(PHP8)
PHP8では、コンストラクタの引数にアクセス修飾子を付けるだけでプロパティの定義と代入を同時に行えます。 従来の書き方との違いを問う問題が出題されるため、両方の書き方を読めるようにしておきましょう。
// PHP8のコンストラクタプロモーション:
// 引数にアクセス修飾子を付けるとプロパティ定義と代入を省略できる
class Product
{
public function __construct(
public string $name,
private int $price,
) {}
}
$product = new Product('みかん', 100);
echo $product->name; // みかん
アクセス修飾子(可視性)
| 修飾子 | クラス内 | 子クラス | 外部 |
|---|---|---|---|
public | ○ | ○ | ○ |
protected | ○ | ○ | × |
private | ○ | × | × |
「privateプロパティに外部からアクセスするとどうなるか」(Fatal errorになる)は定番の出題です。 protectedは子クラスからはアクセスできる点がprivateとの違いです。
class Sample
{
private string $secret = '非公開';
}
$sample = new Sample();
echo $sample->secret; // Fatal error: Cannot access private property
継承とオーバーライド
extendsで親クラスを継承し、同名メソッドを子クラスで再定義(オーバーライド)できます。
親クラスのメソッドを呼びたいときはparent::メソッド名()を使います。
PHPの継承は単一継承(extendsに書けるクラスは1つ)である点も頻出です。
class Animal
{
public function speak(): string
{
return '...';
}
}
class Dog extends Animal
{
public function speak(): string // オーバーライド
{
return 'ワン!';
}
}
$dog = new Dog();
echo $dog->speak(); // ワン!
抽象クラスとインターフェイス
| 抽象クラス(abstract) | インターフェイス(interface) | |
|---|---|---|
| インスタンス化 | できない | できない |
| 実装を持つメソッド | 持てる | 持てない(宣言のみ) |
| 利用方法 | extends(1つだけ) |
implements(複数可) |
| プロパティ | 持てる | 持てない(定数は持てる) |
interface Shape
{
public function area(): float; // 実装は持てない(宣言のみ)
}
abstract class Figure
{
abstract public function name(): string; // 抽象メソッド
public function describe(): string // 通常のメソッドも持てる
{
return 'これは図形です';
}
}
class Circle extends Figure implements Shape
{
public function __construct(private float $radius) {}
public function name(): string
{
return '円';
}
public function area(): float
{
return $this->radius ** 2 * M_PI;
}
}
staticプロパティ・staticメソッド
staticを付けたメンバはインスタンス化せずに
クラス名::でアクセスできます。
クラス内部からはself::を使い、
$thisが使えない点が引っかけとして問われます。
class Counter
{
public static int $count = 0;
public static function increment(): void
{
self::$count++; // staticメンバはself::でアクセス
}
}
Counter::increment();
Counter::increment();
echo Counter::$count; // 2(インスタンス化せずに使える)
試験の引っかけポイント
① $this と self:: の使い分け
$thisはインスタンスメンバ、self::はstaticメンバ・クラス定数へのアクセスに使います。
staticメソッドの中で$thisを使うコードは誤りです。
② 抽象クラス・インターフェイスは new できない
new Shape()のように抽象クラスやインターフェイスを直接インスタンス化するコードはFatal errorになります。
「このコードの実行結果は?」という形式でよく出題されます。
③ インターフェイスの実装漏れはエラーになる
implementsしたインターフェイスのメソッドを1つでも実装し忘れると、
そのクラスはFatal errorになります(abstractクラスにすれば実装を先送りできます)。