• ベストアンサー

protectedなのにアクセスできないのは何故

PHP初心者というより、 これはプログラム初心者と言うべきでしょうか。 まず、ソースコードを見て下さい。 <?php //スーパークラスfooの定義 class foo { //xはprotected protected $x = 10; //yはprivate private $y = 10; } //サブクラスhogeの定義 class hoge extends foo { public function getX(){ return $this->x; } public function getY() { return $this->y; } } $o = new hoge(); echo "x = ".$o->getX()."(メソッド経由)\n"; echo "y = ".$o->getY()."(メソッド経由)\n"; echo "y = ".$o->y."(直接参照)\n"; echo "x= ".$o->x."(直接参照)\n"; var_dump($o); ?> これだと echo "x= ".$o->x."(直接参照)\n"; の部分がエラーになるんですよね。 $oはhogeクラスでfooクラスのサブクラスですよね。 なので、 echo "x= ".$o->x."(直接参照)\n"; これが何故エラーになるのか分かりません。 厚かましいとは存じますが、低レベルな質問なんですけど、 オブジェクト指向のプログラムを学ぶ上で基本的な部分なので、 バカにでも分かる回答を宜しくお願い致したいと思う次第です。

  • PHP
  • 回答数2
  • ありがとう数3

質問者が選んだベストアンサー

  • ベストアンサー
noname#94983
noname#94983
回答No.2

protectedを勘違いしているんじゃないかと思う。 protectedは、「そのクラスおよびそのサブクラス内からのみアクセスが許可される」というもの。したがって、サブクラスに用意されたメソッドからは利用することができる。この「サブクラス内からアクセスできる」という部分の意味を勘違いしているのだと思う。 $o->x というのは、サブクラスhoge内で実行してはいない、ということはわかるだろうか。サブクラス以外のところからhogeクラスのインスタンスを作り、そのprotectedメンバにアクセスしようとしている。つまり、これは「サブクラスではないところから、サブクラス内のprotectedメンバ変数を呼び出している」わけで、protectedの許可していないアクセスだから値は取得できない。 もし、これが許可されてしまうと、protectedの意味がなくなる(要するに、どこからでもアクセスできてしまうわけだから)。protectedは、サブクラス内に用意されているメンバ内でのみ限定的に利用できるものであって、「サブクラスのインスタンスを介せばどこからでもアクセスできる」ものではない、ということ。

persona
質問者

お礼

logger_manさん、いつも丁寧なアドバイス感謝しています。 >$o->x というのは、サブクラスhoge内で実行してはいない、ということはわかるだろうか。 ここが分からないですね。 >サブクラス以外のところからhogeクラスのインスタンスを作り、そのprotectedメンバにアクセスしようとしている。 これは、hogeクラスのインスタンスは全てfooクラスのサブクラスでは無いと理解していいのでしょうか。 >つまり、これは「サブクラスではないところから、サブクラス内のprotectedメンバ変数を呼び出している」わけで、protectedの許可していないアクセスだから値は取得できない。 なるほど。 1番目が理解できず、2番目は再確認で、3番目は納得という感じですかね。

その他の回答 (1)

  • inu2
  • ベストアンサー率33% (1229/3720)
回答No.1

外部から直接参照させたい場合は、 public $x; と定義してください。 protectedは継承したクラス内でのみ有効 privateはそのクラス内でのみ有効 ってか、 echo "y = ".$o->y."(直接参照)\n"; ここでもエラーが出るはずですが・・・ 個人的には、クラス内変数を直接参照させること自体が気に入りませんが・・・・

persona
質問者

お礼

アドバイスありがとうございます。 ここが分からないんですけど、$oはhogeクラスでfooクラスのサブクラスですよね。 何故直接参照するとエラーなんでしょうか。 10が表示されると思うのですが、間違いないんですよね。 その根本が理解できないんですよね。 プロパティyはprivateなので存在しないnull値で表示されるらしいです。

関連するQ&A

  • protectedなのにアクセスできないのは何故 その2

    PHP初心者というより、 これはプログラム初心者と言うべきでしょうか。 もう1度同じ内容の質問をします。 それだけ物凄く困っています。 どうか手助けをお願い致します。 まず、ソースコードを見て下さい。 <?php //スーパークラスfooの定義 class foo { //xはprotected protected $x = 10; //yはprivate private $y = 10; } //サブクラスhogeの定義 class hoge extends foo { public function getX(){ return $this->x; } public function getY() { return $this->y; } } $o = new hoge(); echo "x = ".$o->getX()."(メソッド経由)\n"; echo "y = ".$o->getY()."(メソッド経由)\n"; echo "y = ".$o->y."(直接参照)\n"; echo "x= ".$o->x."(直接参照)\n"; var_dump($o); ?> これだと echo "x= ".$o->x."(直接参照)\n"; の部分がエラーになるんですよね。 $oはhogeクラスでfooクラスのサブクラスですよね。 なので、 echo "x= ".$o->x."(直接参照)\n"; これが何故エラーになるのか分かりません。 ここで確認ですが、$oはhogeのインスタンスではあるが、fooのサブクラスhogeとは別物である。 この解釈でいいんでしょうか。 どうぞ宜しくお願い致します。

    • ベストアンサー
    • PHP
  • protectedについて

    メソッドの前につけるprotectedについてなんですが 具体的にどこまでアクセスを許可するのでしょうか? 調べたところサブクラスと同じクラス内はいけるようですが 同じパッケージ内ではだめなのでしょうか?

    • ベストアンサー
    • Java
  • protectedメソッドが使用できる範囲

    protectedメソッド(もしくはコンストラクタ)はサブクラスからであればアクセスできると覚えていたのですが、以下のような使い方だとサブクラスから見えなくなるようです。 サブクラスでも別パッケージからは参照できないのでしょうか。 ------------------------- package sample.a; import sample.b.*; public class Main2 { public Main2() { } protected Main2(int a){ }     protected void hoge(){ } } -------------------------- package sample.b; public class Main extends Main2{ public void hoge(){ Main2 m2 = new Main2(1);//ここでエラー m2.hoge(); //この使い方もエラー } } -------------------------------

    • ベストアンサー
    • Java
  • 【Ruby】Protectedの確認プログラム

    こんにちは、Ruby初学者です。 以下の問題が解けずに困っています。「protectedが、メソッドをクラス内部から使えるようにする。また、同一クラス内ではインスタンスメソッドとしても使えるようにする。」という教科書的な内容は理解しているつもりでプログラムを書くのですが、どうも上手くいきません。 ヒントだけでも構いませんので、諸兄姉の知識をお貸しいただければ幸いです。 「protectedと宣言されたメソッドは、そのメソッドが定義されているクラスのサブクラスで定義されているメソッドから、メッセージの送信元とは異なるオブジェクトに対しても呼び出せることを確認するプログラムを作成し、結果を説明せよ。」 よろしくおねがいいたします。

    • ベストアンサー
    • Ruby
  • アクセス修飾子

    アクセス修飾子 が理解できません。 ヘルプやインターネットで調べると下記のようにかかれています。 public 『アクセスの制限はありません。 』 protected 『アクセスは、コンテナ クラス、またはコンテナ クラスから派生した型に制限されます。 』 internal 『アクセスは現在のプロジェクトに制限されます。 』 protected internal 『アクセスは、現在のプロジェクト、またはコンテナ クラスから派生した型に制限されます。 』 private 『アクセスはコンテナ型に制限されます。』 public 、private は理解できるのですが、protected 、internal が理解できません。 Javaだとprotectedは同じパッケージ内、サブクラスでアクセス可能とかかれています。 .NETも同じでしょうか? 同じパッケージ内?ってどういうこと?となっています。 1つのオブジェクト内に2つのクラスを作成し、 クラスAのメソッドに protectedで作成し 、クラスBでクラスAの宣言をしたらAのprotectedのメソッドは使用できません。どういう場合にprotectedのメソッドは使用できるのでしょうか?

  • 派生クラスから基本クラスprotectedメンバへのアクセスについて

    C++初心者です。 以下のような基本クラスcoordと、その派生クラスquadがあり、quadクラスに関して=演算子をオーバーロードしました。 class coord { protected: int x, y; }; class quad : public coord { public: quad operator=(coord &ob2); }; quad quad::operator=(coord &ob2) { x = ob2.x; y = ob2.y; } するとob2からxにアクセスできないとエラーが出ます。 quadクラスのメンバ関数内なので、基本クラスのprotectedメンバにはアクセスできると思ったのですが、違うのでしょうか。 ご教授お願いします。

  • MouseEventおよびMouseListenerについて、、

    JAVAの初心者です。。 ただいまMouseEventおよびMouseListenerをもちいて、 とある画像でMouseを用いた距離の測定を行うプログラムを作成中なのですが、、 public void run(){ addMouseListener(this) } public void mouseClicked(MouseEvent e){} public void mousePressed(MouseEvent e){ int x1 = e.getX(); int y1 = e.getY(); } public void mouseReleased(MouseEvent e){ int x2 = e.getX(); int y2 = e.getY(); Line = Math.sqrt((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1)); } public void mouseEntered(MouseEvent e){] public void mouseExites(MouseEvent e){} プログラムとしてはプレスとリリースで直線距離を測定し、 その後、その距離を用いて他の計算を行うものなのですが、 mouseReleased時にgetX()メソッドをもちいて測定した距離(変数Line)を他のクラスに継承させたいのですがうまくいかないのです。 mouseReleasedメソッドにSystem.out.println(Line)を加えると確かに期待通りの値が出るのですが、 return Line;ではMouseEventメソッドにvoidをつけなければならないために不具合が生じてしまいます。 この変数Lineを他のクラスで使用する場合どのようにすればよいでしょうか、ご指導おねがいします。 また、もう一つの問題点として、このMouseEventを一度起動させると何度マウスを動かしても何度も処理をおこなってしまいます。このMouseEventの終了(可能ならばmouseReleased時に終了)させるためにはどのようなメソッドを加える必要があるでしょうか?? あわせてご教授願います。。

    • ベストアンサー
    • Java
  • javaアプレット

    javaアプレットの勉強をしているのですが、教えてください。 マウスを押すと位置を取得して、線を描くアプレットをつくってみたいと思っています。 一回目に押した位置を始点として、二回目の位置まで線を引きます。このとき、二回目にマウスを押したときにはじめて線を描画するとします。その後、三回目、四回目とマウスを押していくと、前に押した位置を始点として線を引くようなアプレットです。 そこで以下のようにコードを書いて実行してみました。(部分) public void mousePressed(MouseEvent e) { n=n+1; if(n==1){ x1=e.getX(); y1=e.getY();} else{ x2=e.getX(); y2=e.getY(); repaint(); x1=x2; y1=y2; } } public void paint(Graphics g) { g.drawLine(x1,y1,x2,y2); } ところが、実行してみると、マウスを押す位置に点が移動するだけでした。おそらく、コード中のx1=x2;y1=y2;がrepaint();より前に実行されてしまうのではないかと思います。どう書き直せばいいのでしょうか?また、どうしてrepaint();より前に実行されてしまうのでしょうか?

    • ベストアンサー
    • Java
  • classを使って座標軸を求めるコード

    やさしいJavaからの問題です。 次のように、整数値の座標をあらわす MyPoint クラスを作成してください。 フィールド private int x; (X座標) private int y; (Y座標) メソッド public void setX(int px); (X座標を設定する) public void setY(int py); (Y座標を設定する) public int getX(); (X座標を得る) public int setY(); (Y座標を得る) という問題で、回答は以下の通りですが、 class MyPoint { int x; int y; void setX(int px) { x = px; } void setY(int py) { y = py; } int getX() { return x; } int getY() { return y; } } class Sample5 { public static void main(String[] args) { MyPoint p1; p1 = new MyPoint(); p1.setX(10); p1.setY(5); int px = p1.getX(); int py = p1.getY(); System.out.println("p1のX座標は" + px + "Y座標は" + py + "でした。"); } } 教科書の関連の章ではreturnが先に来ているのですが、突然この問題ではvoidから始まっているのですが、int getX()~return y;までとvoid setX~y = py;までの部分 の順番を変えてもいいですか?

    • ベストアンサー
    • Java
  • Unix初心者による初心者シェルプログラミングです。

    Unix初心者による初心者シェルプログラミングです。 以下のようなコマンドを羅列しただけの スクリプトが300行(実質100行ぐらい)が漸くできるようになりました。 これだけで、おばかさんな私は進化してます。が・・・ 対象となる、hoge.txtは、同ディレクトリ内に別名で、200ファイル有ります。 このスクリプトがその別名、200ファイルへと対象になります。 と云う事はファイル名分の200ファイル分スクリプトを編集して用意しなくては いけなくなる。 となると・・・ 別の事をしないといけませんよね。 どうやら、同ディレクトリ内にある、全ての .txt ファイルに対してこの スクリプトを実行させるには・・・ (よくわかりませんが・・・) FILE=`/home/foo/*.txt` みたいな・・・(全然違うと思っていますが、イメージで) /home/foo/ 内の .txt ファイルを一ファイルずつ読み込んで、実行させる方法が あると思うのですが・・・ 全てを教えて貰うつもりはありません。 学習していきます。 でも、疲れてきました。 がしかし、やらなくちゃいけません。 ヒント下さい。 お願いします! > cat hogehoge.sh #!/usr/bin/sh DAY=`/usr/xpg4/bin/date '+%Y/%m/%d%a'` HUMAN=`/usr/ucb/whoami` TIME=`/usr/xpg4/bin/date '+%H:%M:%S'` echo echo "$DAY : $HUMAN : PID $$" echo echo "$0" echo echo "$TIME Let's start!" echo echo "ls -l /home/foo/hoge.txt" ls -l /home/foo/hoge.txt echo echo "cat -n /home/foo/hoge.txt | head -15" cat -n /home/foo/hoge.txt | head -15 echo echo "sed -f /home/foo/script.sed /home/foo/hoge.txt > /home/foo/new-hoge.txt" sed -f /home/foo/script.sed /home/foo/hoge.txt > /home/foo/new-hoge.txt echo echo "ls -l /home/foo/new-hoge.txt" ls -l /home/foo/new-hoge.txt echo echo "cat -n /home/foo/new-hoge.txt | head -18" cat -n /home/foo/new-hoge.txt | head -18 echo echo "sed -e '1d' -e '14d' /home/foo/new-hoge.txt > /home/foo/renewal-hoge.txt" sed -e '1d' -e '14d' /home/foo/new-hoge.txt > /home/foo/renewal-hoge.txt echo echo "ls -l /home/foo/renewal-hoge.txt" ls -l /home/foo/renewal-hoge.txt echo echo "diff /home/foo/new-hoge.txt /home/foo/renewal-hoge.txt" diff /home/foo/new-hoge.txt /home/foo/renewal-hoge.txt echo echo "sed -e '13d' -e 's/^iranai/hitsuyou/' /home/foo/renewal-hoge.txt > /home/foo/new-hoge.txt" sed -e '13d' -e 's/^iranai/hitsuyou/' /home/foo/renewal-hoge.txt > /home/foo/new-hoge.txt echo echo "ls -l /home/foo/new-hoge.txt" ls -l /home/foo/new-hoge.txt echo ・ ・ ・ ・ ・ ・ ・ ・ 300

専門家に質問してみよう