gallu’s blog

エンジニアでゲーマーで講師で占い師なおいちゃんのブログです。

「列挙型をよこせ!」

いやまぁふと思いついたのですが…まぁ以前から定期的に思ってたんですがね「列挙型はどこだ!」。


こんな感じのをイメージしてまふ。
おいちゃんはC言語方面から歩んできている旅人なんでね。

#include <stdio.h>

// 列挙型の宣言
enum cardsuit {
  CLUBS,
  DIAMONDS,
  HEARTS,
  SPADES
};

int main() {
  //
  enum cardsuit s;
  s = CLUBS;

  //
  switch(s) {
    case CLUBS:
      puts("weapons of war.");
      break;
    case DIAMONDS:
      puts("money for this art.");
      break;
    case SPADES:
      puts("swords of a soldier.");
      break;
    case HEARTS:
      puts("that's not the shape of my heart.");
      break;
  }

  //
  return 0;
}

元ネタはキニスンナ。


ここから考えるに、大体、こんな感じで使いたいわけですよ。PHP的には。

<?php

// 列挙型の宣言
class cardsuit extends enum {
  // XXX ここの宣言はイメージもやもやっと
  CLUBS,
  DIAMONDS,
  HEARTS,
  SPADES
};

  //
  $s = cardsuit::CLUBS;

  //
  switch($s) {
    case cardsuit::CLUBS:
      echo("weapons of war.");
      break;
    case cardsuit::DIAMONDS:
      echo("money for this art.");
      break;
    case cardsuit::SPADES:
      echo("swords of a soldier.");
      break;
    case cardsuit::HEARTS:
      echo("that's not the shape of my heart.");
      break;
  }


で。
ふと思いついたのが「マジックメソッド使えばいいんじゃね?」的な。
つまり、こう。

// 列挙型の宣言
class cardsuit extends enum {

// 要素の宣言
protected $contents = array(
  'CLUBS',
  'DIAMONDS',
  'HEARTS',
  'SPADES'
);

};

で、switch文とかを、こう。

  //
  $s = cardsuit::$CLUBS;

  //
  switch($s) {
    case cardsuit::$CLUBS:
      echo("weapons of war.");
      break;
    case cardsuit::$DIAMONDS:
      echo("money for this art.");
      break;
    case cardsuit::$SPADES:
      echo("swords of a soldier.");
      break;
    case cardsuit::$HEARTS:
      echo("that's not the shape of my heart.");
      break;
  }


これだと本当にギリギリまで「書いている文字的に、C言語に似てる」から、おいちゃん的によひわひなぁ、とか思う訳です。
とりあえず、躊躇無く、enumクラスを実装してみる。

class enum {
  // newはでけないように
  private function __construct() {
  }

  // 値の設定も却下する!
  public function __set ($name , $value) {
    throw new Exception('列挙型に代入とか、なめてる?');
  }

  //
  public function __get ($name) {
    // 反転したほうが扱いやすいので
    if (false === self::$flip_flg_) { // ここは「あえての」self
      static::$contents = array_flip(static::$contents);
    }
    //
    if (false === isset(static::$contents[$name])) {
      throw new Exception('ンな値、ないよ?');
    }
    // else
    return static::$contents[$name];
  }

//
private static $flip_flg_ = false;
};

// 列挙型の宣言
class cardsuit extends enum {
// 要素の宣言
protected static $contents = array(
  'CLUBS',
  'DIAMONDS',
  'HEARTS',
  'SPADES'
);

};

  // データをげと部分
  $s = cardsuit::$CLUBS;

  // データを判定部分(結局、げとなのだが)
  switch($s) {
    case cardsuit::$CLUBS:
      echo("weapons of war.");
      break;
    case cardsuit::$DIAMONDS:
      echo("money for this art.");
      break;
    case cardsuit::$SPADES:
      echo("swords of a soldier.");
      break;
    case cardsuit::$HEARTS:
      echo("that's not the shape of my heart.");
      break;
  }

動かしてみる。

Fatal error: Access to undeclared static property: cardsuit::$CLUBS in

…動かない orz


いいぢゃん__callに対して__callStaticがあるんだから、__getと__setに、__getStaticと__setStatic作ろうよ!
どうも議論している形跡と気配と痕跡はあるんですがねぇ…実装してくんねぇかなぁ…


ってな訳で、挫折の記録を残しておきまする orz