Scala: How do I dynamically instantiate an object and invoke a method using reflection?
にサンプルがあったのでメモ。
class Foo {
def hello(name: String): String = "Hello there, %s".format(name)
}
object FooMain {
def main(args: Array[String]) {
val foo = Class.forName("Foo").newInstance.asInstanceOf[{ def hello(name: String): String }]
println(foo.hello("Walter")) // prints "Hello there, Walter"
}
}
この方法を利用すると以前書いたAbstractFactoryのサンプルをこれで書きかえることができるので書きかえてみた。// ラジオボタンのアクションを設定する
reactions += {
case ButtonClicked(b) => b.text match {
case "菜園" => {
garden = new VegieGarden
gardenPlot.clearPlants
}
case "一年草園" => {
garden = new AnnualGarden
gardenPlot.clearPlants
}
case "多年草園" => {
garden = new PerennialGarden
gardenPlot.clearPlants
}
}
}
の部分は// ラジオボタンのアクションを設定する
reactions += {
case ButtonClicked(b) => {
garden = Class.forName(buttonMap.getOrElse(b.text, "")).newInstance.asInstanceOf[Garden];
gardenPlot.clearPlants;
}
}
だけでOKになる。 全ソースはこちら import java.awt.Color
import scala.swing._
import scala.swing.event._
/**
* メインオブジェクト
*/
object Gardener extends SimpleSwingApplication {
def top = new MainFrame {
title = "AbstractFactory Sample"
var garden:Garden = new NoGarden
val gardenPlot = new GardenPanel{background = Color.WHITE};
val buttonMap = Map("菜園" -> "VegieGarden"
, "一年草園" -> "AnnualGarden"
, "多年草園" -> "PerennialGarden");
// ButtonGroupの生成と設定
val group = new ButtonGroup
for ((key, value) <- buttonMap) {
val button = new RadioButton(key)
group.buttons += button
listenTo(button)
};
contents = new GridPanel(1,2) {
// 左パネルの生成
contents += new GridBagPanel {
val constraints = pair2Constraints(0, 0)
constraints.anchor = GridBagPanel.Anchor.FirstLineStart
layout += new Label("庭園の種類") -> constraints;
// ラジオボタンを配置する
for (i <- 0 to (group.buttons.toList.length - 1)) {
val constraints = pair2Constraints(0, (i + 1));
constraints.anchor = GridBagPanel.Anchor.FirstLineStart
constraints.ipady = 70
layout += group.buttons.toList(i) -> constraints
}
}
// 右パネルの生成
contents += new GridBagPanel {
val constraints = pair2Constraints(0, 0);
constraints.ipady = 210
constraints.ipadx = 210
constraints.gridwidth = 3
constraints.fill = GridBagPanel.Fill.Horizontal
constraints.insets = new Insets(10, 5, 0, 5)
layout += gardenPlot -> constraints
// ボタンの生成と設定
val list = List("Center", "Border", "Shade")
for (i <- 0 to (list.length - 1)) {
setButton(list(i), i, 1)
}
setButton("Quit", 1, 2)
/**
* ボタンを生成し、パネル上に配置する
*
* @param String buttoName
* @param Int x
* @param Int y
* @return Unit
*/
private def setButton(buttonName:String, x:Int, y:Int) = {
val button = new Button(buttonName)
val const = pair2Constraints(x, y);
const.insets = new Insets(10, 5, 0, 5)
layout += button -> const
listenTo(button)
}
// ボタンのアクションを設定する
reactions += {
case ButtonClicked(b) => b.text match {
case "Center" => {
gardenPlot.centerPlant = garden.center.name
gardenPlot.repaint
}
case "Border" => {
gardenPlot.borderPlant = garden.border.name
gardenPlot.repaint
}
case "Shade" => {
gardenPlot.shadePlant = garden.shade.name
gardenPlot.repaint
}
case "Quit" => System.exit(0)
}
}
}
}
// ラジオボタンのアクションを設定する
reactions += {
case ButtonClicked(b) => {
garden = Class.forName(buttonMap.getOrElse(b.text, "")).newInstance.asInstanceOf[Garden];
gardenPlot.clearPlants;
}
}
}
}
/**
* 植物を表すクラス
*/
case class Plant(name:String)
/**
* 庭トレイと
*/
trait Garden {
def shade:Plant
def center:Plant
def border:Plant
}
/**
* デフォルトの庭クラス
*/
class NoGarden extends Garden {
def shade = new Plant("")
def center = new Plant("")
def border = new Plant("")
}
/**
* 一年草園の庭クラス
*/
class AnnualGarden extends Garden {
def border = Plant("アブラナ")
def center = Plant("キンセンカ")
def shade = Plant("コレウス")
}
/**
* 多年草園の庭クラス
*/
class PerennialGarden extends Garden {
def border = Plant("ベンケイソウ")
def center = Plant("ケマンソウ")
def shade = Plant("チダケサシ")
}
/**
* 菜園の庭クラス
*/
class VegieGarden extends Garden {
def border = Plant("エンドウ")
def center = Plant("トウモロコシ")
def shade = Plant("ブロッコリ")
}
/**
* 庭の様子を表示するパネル
*/
class GardenPanel extends Panel {
var borderPlant = "";
var centerPlant = "";
var shadePlant = "";
var garden = new NoGarden
def clearPlants = {
borderPlant = ""
centerPlant = ""
shadePlant = ""
repaint()
}
override def paint(g:Graphics2D) = {
super.paint(g)
g.setColor(Color.LIGHT_GRAY)
g.fillArc(1, 1, 80, 80, 0, 360)
g.setColor(Color.BLACK)
g.drawRect(0, 0, size.width - 1, size.height - 1)
g.drawString(centerPlant, 100, 50)
g.drawString(borderPlant, 75, 120)
g.drawString(shadePlant, 10, 40)
}
}
※追伸 >- この投稿が役にたったと思った方は、上か下の広告をクリックしていただけるとうれいいです。
0 件のコメント:
コメントを投稿