ITコンサルの日常

ITコンサル会社に勤務する普通のITエンジニアの日常です。

動的にクラスを生成

RubyではStructクラスを使うと、データを格納するだけのクラスを作成できるそうです。

# Personクラスを定義
Person = Struct.new("Person", "name", "address", "tel")

taro = Person.new("Taro", "Tokyo", "03-3xxx-xxxx")
hanako = Person.new("Hanako", "Osaka", "06-xxxx-xxxx")

p [taro.name, taro.address, taro.tel]
p [hanako.name, hanako.address, hanako.tel]

結構便利そう。ちなみにJavaScriptでもFunctionコンストラクタ使えば同じようなことが出来ます。

var Person = new Function("name", "address", "tel", "{ \
        this.name = name; \
        this.address = address; \
        this.tel = tel; \
}");

var taro = new Person("taro", "Tokyo", "03-3xxx-xxxx")
var hanako = new Person("hanako", "Osaka", "06-xxxx-xxxx")

WScript.Echo(taro.name, taro.address, taro.tel)
WScript.Echo(hanako.name, hanako.address, hanako.tel)

cscriptで実行します。

>cscript //NoLogo struct.js
taro Tokyo 03-3xxx-xxxx
hanako Osaka 06-xxxx-xxxx

>

Javaでやるには、Javassist使えば出来ます。が、Personって直接書けないので非常に苦しい。。

import javassist.*;

public class struct
{
        public static void main(String[] args) throws Exception
        {
                // Personクラスを定義
                ClassPool cp = ClassPool.getDefault();
                CtClass cc = cp.makeClass("Person");
                CtField f1 = CtField.make("public String name;", cc);
                cc.addField(f1);
                CtField f2 = CtField.make("public String address;", cc);
                cc.addField(f2);
                CtField f3 = CtField.make("public String tel;", cc);
                cc.addField(f3);
                cc.writeFile();

                Class c = Class.forName("Person");
                Object taro = c.newInstance();
                c.getField("name").set(taro, "taro");
                c.getField("address").set(taro, "Tokyo");
                c.getField("tel").set(taro, "03-3xxx-xxxx");

                Object hanako = c.newInstance();
                c.getField("name").set(hanako, "hanako");
                c.getField("address").set(hanako, "Osaka");
                c.getField("tel").set(hanako, "06-xxxx-xxxx");

                System.out.println((String)c.getField("name").get(taro)+" "+
                                   (String)c.getField("address").get(taro)+" "+
                                   (String)c.getField("tel").get(taro));
                System.out.println((String)c.getField("name").get(hanako)+" "+
                                   (String)c.getField("address").get(hanako)+" "+
                                   (String)c.getField("tel").get(hanako));
        }
}