質問編集履歴

1 参考質問を追加

raccy

raccy score 19450

2017/04/27 19:48  投稿

class内のconstは後から定義しても良いのはなぜか?
PHPの`const`について、
```PHP
<?php
const Y = "hoge";
const X = Y;
var_dump(X);
```
これは`string(4) "hoge"`が表示されます。では、
```PHP
<?php
const X = Y;
const Y = "hoge";
var_dump(X);
```
とすると、Yを定義せずに使っているという警告と共に`string(1) "Y"`が表示されます。ではでは、
```PHP
<?php
class A {
   const X = A::Y;
   const Y = "hoge";
}
var_dump(A::X);
```
とすると、`string(4) "hoge"`が表示され、定義前の`A::Y`を見に行けているようです。
どうしてclass外では後方のconstを参照することはできないのに、class内だとできるのでしょうか?そのとき、どのような順番で何を処理しているのでしょうか?
###他の言語からの考察
C++はそもそも前方に宣言がないと使えないので、宣言があることが前提になります。char *のようなポインタだと逆順でも同じ物になりますが、std::stringのようなものでは逆順だと結果が変わります。
```C++
#include <iostream>
#include <string>
class A
{
public:
   static const char *const XC;
   static const char *const YC;
   static const std::string XS;
   static const std::string YS;
};
const char *const A::XC = YC;
const char *const A::YC = "hoge";
const std::string A::XS = YS;
const std::string A::YS = "hoge";
int main()
{
   std::cout << A::XC << std::endl; // hoge
   std::cout << A::XS << std::endl; // (空)
   return 0;
}
```
Javaはコンパイル時にエラーになります。
```Java
class A {
   public static final String X = Y; // エラー: 前方参照が不正です
   public static final String Y = "hoge";
   public static void main(String[] args) {
       System.out.println(X);
   }
}
```
Rubyは未定義であるとして同じくエラーになります。
```Ruby
class A
 X = A::Y # uninitialized constant A::Y (NameError)
 Y = "hoge"
end
p A::X
```
Haskellはオブジェクト指向におけるクラスに相当する物はないですが、通常の定数(そもそも全てが定数ですが)についても、遅延評価なので、順番とかはなんも関係無く動作できます。
```Haskell
x = y
y = "hoge"
main = print x -- "hoge"
```
C++がそういう動作になる理由はちょっと複雑になるので除きますが、JavaやRubyはclass内の定数であっても、定義されていない定数は使えません。定数の定義処理を順番にしていくと考えれば妥当な仕様だと思います。しかし、PHPだと、順番に定義していくと考えることはできません。となると、`A::Y`部分をHaskellのように遅延評価しているとか、そんな感じなのでしょうか?
###参考にした質問  
 
[PHP - 定数の定義より前にその定数を使う関数の定義を書いても大丈夫なのか(73837)|teratail](https://teratail.com/questions/73837)  
上の質問については、関数内の式の評価が呼び出し時だから問題ないという物です。では、constの右辺の評価も呼び出し時だから…と考えると、Xの右辺が評価されるときにYの右辺が評価済みというのもおかしな話ですし、class外だとうまくいかない理由も付けられなくなります。  
 
---
[定数式のバグ - Qiita](http://qiita.com/rana_kualu/items/4cf44c3a47071d40280b)を読んで、ふと気になりました。なお、この現象は記事に書いているバグと関係はありますが、バグそのもののことではありません。
[定数式のバグ - Qiita](http://qiita.com/rana_kualu/items/4cf44c3a47071d40280b)を読んで、ふと気になりました。なお、この現象は記事に書いているバグと関係はありますが、バグそのもののことではありません。
  • PHP

    29206 questions

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

思考するエンジニアのためのQ&Aサイト「teratail」について詳しく知る