質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

オブジェクト指向

オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。

Q&A

解決済

2回答

1487閲覧

$thisが指すクラスがどれかわかりません。

awa

総合スコア34

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

オブジェクト指向

オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。

0グッド

0クリップ

投稿2018/06/30 05:22

下記のコードを実行すると、ブラウザには"さん、こんにちは。"という表示になりましたが、なぜその表示になるのかわからないので教えていただけないでしょうか。
想定していたのは、"ゲストさん、こんにちは。"でした。

php

1class User{ 2 private $name = null; 3 4 public function print_hello(){ 5 print $this->name; 6 print "さん、こんにちは。"; 7 } 8} 9 10class Guest extends User{ 11 private $name = "ゲスト"; 12} 13 14$guest = new Guest(); 15$guest->print_hello();

下記のように認識しています。
$guestにはGuestクラスのインスタンスが入っており、GuestクラスはUserクラスを継承している。
Guestクラスは継承しているため、Userクラスのprint_hello()を持っている。
Guestクラスにあるprint_hello()を呼び出すことで、$this->nameでGuestの$nameにアクセスする。

このような結果になったので、$this->nameがUserクラスの$nameにアクセスしているんだろうなと思ってはいるのですが、なぜGuestのインスタンスから読んだのに、$thisがUserクラスを指すのかがわかりません。

どうぞよろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

Guestの$nameはprivateだからUserのメソッドからは参照できない

プロパティとしては両方保持しているが
どちらのクラスのメソッドで呼ばれたかでどっちが取得されるかが変わる

こうするとわかりやすい

php

1class hoge{ 2 private $name='a'; 3} 4class hoge2 extends hoge{ 5 private $name='b'; 6} 7 8$hoge2=new hoge2(); 9var_dump(new hoge2()); 10/* 11object(hoge2)#1 (2) { ["name":"hoge2":private]=> string(1) "b" ["name":"hoge":private]=> string(1) "a" } 12*/

両方のプロパティがちゃんといる

protectedなら上書きされて一つだけになる

php

1class hoge{ 2 protected $name='a'; 3} 4class hoge2 extends hoge{ 5 protected $name='b'; 6} 7 8$hoge2=new hoge2(); 9var_dump(new hoge2()); 10/* 11object(hoge2)#2 (1) { ["name":protected]=> string(1) "b" } 12*/

投稿2018/06/30 06:18

KazuhiroHatano

総合スコア7802

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

awa

2018/06/30 13:26

ご回答ありがとうございます。 おかげで私が下記2点誤解していたことがわかり、今回の結果原因について理解できました。 (1) 継承したら同じ名前のプロパティとメソッドは全てオーバーライドされる。   (→継承元がpublicとprotectedならアクセスが可能なためオーバーライドになるが、privateはオーバーライドされずにそのまま同名でも両方とも継承先で保持される。) (2) 継承先でメソッドを明記していなくても、継承すればスーパークラスのメソッドが継承先のクラス内に自身のメソッドとしてコピーされている。 (→継承先でそのメソッドを定義していなければ、スーパークラスのメソッドを呼んでいる。今回の場合は、print_hello()はGuestクラスのメソッドではなくUserクラスのメソッドを呼んでいる。nameがUserとGuestクラスの両方あるが、メソッドはUserクラスのものなので、Userクラスのnameが採用される。一方でもし、nameがオーバーライドされて1つしかなかった場合、メソッドはUserクラスのものが呼ばれるが、オーバーライドした方のnameが採用される。) (2)で書いた「一方でもし~」の部分が例外のような感じで$thisが指すオブジェクトが異なってくるのがややこしいなと感じました。 もし理解が違っていればお手数ですがご指導お願いいたします。
KazuhiroHatano

2018/06/30 14:52

概ねその理解であっていると思いますが、protectedやpublicではコードで示した通りプロパティは一つになっていてかつどのクラスで定義されたかの情報も保持していません。 スーパークラスで定義されたメソッドがサブクラスから呼び出された際に、呼び出し元のサブクラスを参照するには「静的遅延束縛」を使います、まあ小難しい名前ついてますが要するにstaticでメソッドを実行したクラスを参照できるよって話です。 蛇足ですが、serializeした場合なんかはprivateなのかpublicなのかといったアクセス権の情報も保持しないのですが、どのクラスで定義されたプロパティなのかは保持しています、unserializeの時にアクセス権の情報が元と違っていてもエラーになりません、なのでクラス定義を変えてunserializeすることでprivateなプロパティをpublicにしてしまったりもできたりします。
KazuhiroHatano

2018/06/30 15:00

×静的遅延束縛 ○遅延静的束縛
awa

2018/07/01 07:12

遅延静的束縛、serializeについて全く知らなかったので、そちらも調べてみました。特に遅延静的束縛について調査することでstaticの知識の深まり、どのクラスがスコープになるのかがぼんやりした理解だったのが明らかになりました。ありがとうございました!
guest

0

$nameprivate なので継承してオーバーライドしようとしても、元クラスのメソッドからは元クラスの $name にしかアクセス権がないため null になります。

キーワードアクセス権
privateそのクラスからしかアクセスできない
protectedそのクラスと、サブクラスからしかアクセスできない
publicどこからでもアクセスできる

こういう場合には protected を使いましょう。

php

1class User{ 2 protected $name = null; 3 4 public function print_hello(){ 5 print $this->name; 6 print "さん、こんにちは。"; 7 } 8} 9 10class Guest extends User{ 11 protected $name = "ゲスト"; 12}

投稿2018/06/30 06:16

yhg

総合スコア2161

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

awa

2018/06/30 13:29

ご回答ありがとうございます。 privateやprotectedの存在はテキストで見てはいたのですが、今一理解できていなかったんだなと感じました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問