LoginSignup
0
0

More than 5 years have passed since last update.

[PHP]体重が気になるあなたへ 〜privateの特殊ケース〜

Last updated at Posted at 2019-01-13

皆さん、健康診断の結果はどうでしたか?

えっ、またお医者さんに「太り過ぎ」と言われた?
奥さんに怒られるし、上司からも「痩せろ」と言われるしで、大変ですよね。

だったら、体重は private プロパティーにして秘密にしておきましょう!

class Person
{
  private $name;

  // 最高機密
  private $weight;

  public function __construct($name, $weight)
  {
    $this->name = $name;
    $this->weight = $weight;
  }
}

はい、これで体重を隠せましたね。めでたしめでたし。

メソッドを追加してみる

でも、自分より太ってそうな、あの同僚の体重、知りたいですよね。1

はい、そんなあなたのために、こんなメソッド書いてみました。

class Person
{
  private $name;
  private $weight;

  public function __construct($name, $weight)
  {
    $this->name = $name;
    $this->weight = $weight;
  }

  /**
   * 体重が同じかを比較する
   */
  public function isWeightEqual($other)
  {
    return $this->weight === $other->weight;
  }
}

あっ、でも $other->weightprivate プロパティーだからダメなんじゃない?と思った方。

残念。これはちゃんと動きます。

$a = new Person("山田太郎", 60.5);
$b = new Person("田中次郎", 60.5);
var_dump($a->isWeightEqual($b)); //--> bool(true)

もっと頑張れば、isWeightGreaterThan() とか isWeightLessThan() とかも作れるでしょう。

体重を隠そうとしても無駄なんだぞ!

まじめに考えてみる

実は、PHP マニュアルの 他のオブジェクトからのアクセス権 にちゃんと書いてあります。

同じ型のオブジェクト間では、たとえ同一のインスタンスでなくても お互いの private メンバーや protected メンバーにアクセスすることができます。 これは、そのオブジェクトの内部ではオブジェクトの実装の詳細が既知であるからです。

なんか難しいこと書いてありますが、要するに 同じ型だったらインスタンスが違ってても privateprotected メンバーにアクセスできるぞ と言っています。

なんでこんな面倒なことしてるの?

実は、この仕様、Java でも同じなのですが2[Java]同一クラスであれば他インスタンスのprivateフィールドにアクセスできるのは何故か? という記事に、とても良いコメントを見つけました。

@shirakamus
もし private が thisからしかアクセスできない仕様だったら、equalsメソッドの実装はどうなるかな・・・

Java ではオブジェクトの比較は equals() メソッドで行います。どのオブジェクトも、以下のような Object.equals() を継承しています。

public boolean equals(Object o) {
    return this == o;
}

通常はこれで十分なのですが、equals() メソッドをオーバーライドすることもできます。たしか、こんな感じ。3

public class Person
{
  private String name;
  private double weight;

  Person(String name, double weight)
  {
    this.name   = name;
    this.weight = weight;
  }

  @Override
  public boolean equals(Object other)
  {
    if (this == other) {
      return true;
    }

    if (other instanceof Person) {
      Person person = (Person) other;

      // private フィールドにアクセスしている!!!
      return person.name == this.name
        && person.weight == this.weight;
    }

    return false;
  }
}

重要なのは person.weight == this.weight の部分です。
この person.weight は、引数で渡されたインスタンスの private フィールドですが、同じ Person 型なのでアクセスすることができるわけです。

もし、これが不可能だった場合、person.getWeight() というように、わざわざゲッターを介したアクセスになるでしょう。

まとめ

PHP には Java のような equals() は存在しませんが、思想としてオブジェクト指向を取り入れた際に、Java をはじめとするオブジェクト指向言語と同じような動きをするようにしたのでしょう(たぶん)。

まぁ、積極的に使うべきかと言われると、あんまり知られていないようにも思われるので、止めておいたほうがいいのかなとも思いますが。

あと、そもそも、痩せれば、こんな面倒なことまで気にしなくて済むはずです。

だから、お前は痩せたほうが良い。

(2018/1/13) サブタイトルを付けました。


  1. 知って何が楽しいかって? 「俺はあいつよりも痩せている」という優越感に浸りたいじゃないですか。 

  2. C++ や C# でも同様らしいです。privateメンバ変数へのアクセス 参照。 

  3. 本当は hashCode() もオーバーライドしないといけないらしいけど、一旦、措いておきます。詳しくは equals をオーバーライドする時は一般契約に従う 参照。 

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0