問題
なんか文字列渡ってきてそれに対応するクラスをインスタンス化するみたいなのやったりする。 たとえば
<?php class MyKlass { public $prop = "foo"; public function meth() { echo "This is my method\n"; echo "This.prop = {$this->prop}"; } } $class_name = "MyKlass"; $k = new $class_name(); $k->meth();
class MyKlass: def __init__(self): self.prop = "buz" def meth(self): print("This prop is " + self.prop) mod = { "MyKlass":MyKlass } class_name = "MyKlass" k = mod[class_name]() k.meth()
var module = {}; (function(mod){ var MyKlass = function(){ this.prop = "foo"; this.meth = function(){ console.log("This prop is " + this.prop); } } mod.MyKlass = MyKlass; })(module); var className = "MyKlass"; var k = new module[className](); k.meth();
これ、Go言語でどうやるのかと
調査
- reflect - The Go Programming Language
- reflect パッケージ - golang.jp
- go - is there a way to create an instance of a struct from a string? - Stack Overflow
- Go の interface 設計 - Block Rockin’ Codes
- FAQ - golang.jp
やっぱり、返り値の型を抽象的に宣言する(ジェネリクス的な?)方法が無いから、具体レイヤーでその型にキャストするということが絶対に必要になる、という認識でいいのかな
解決
こんな感じ?
package main import "fmt" import "reflect" // structの定義 type MyKlass struct { Prop string } func (k MyKlass) Meth() { fmt.Printf("This prop is %s", k.Prop) } // 型情報を貯めておく // キー文字列バリュー型情報のmap var typeRegistry = map[string]reflect.Type{} // 型情報を貯めるメソッド func registerType(typ reflect.Type) { typeRegistry[typ.String()] = typ } // まずmainより前に // MyKlassという型を登録しとく func init() { registerType(reflect.TypeOf(MyKlass{})) } func main() { typeName := "main.MyKlass" // ちょっと複雑。 // reflect.Type型を使ってNewして reflect.InterfaceValueをつくる // InterfaceValueをElemでValueにする // Interfaceメソッドでこれをinterface{}にする // interface{}がMyKlassの実装を満たしているか.(type)で調べる k,_ := reflect.New(typeRegistry[typeName]).Elem().Interface().(MyKlass) k.Prop = "foo" k.Meth() }
雑感
うーん、間違ってたら教えてほしい。そして最近つらい。
DRYな備忘録