年明け最初の記事は、Scalaの勉強ということでimplicitを使ってみた話。
Javaの実装でtoHoge()な書式が好きなので、interfaceを使って実現をするのですが、
既存のクラスに関してはそれができません。
その具体例と、対応方法は次のコード。
Outputableを実装したクラスを受け取って出力を行うクラスです。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public interface Outputalbe { | |
public String output(); | |
} |
自前のクラスに関しては、implementsすれば好き勝手に実装ができますね。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class Profile implements Outputalbe { | |
private final String name; | |
private final int age; | |
public Profile(String name, int age) { | |
super(); | |
this.name = name; | |
this.age = age; | |
} | |
@Override | |
public String output() { | |
return String.format("Hey, I am %s , and I'm %d old.", this.name, | |
this.age); | |
} | |
} |
そして出力用のコード。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class Display { | |
public static void main(String[] args) { | |
Display display = new Display(); | |
Outputalbe data = new Profile("numa08", 24); | |
display.out(data); //Hey I am numa08 and , I'm 24 old. | |
} | |
private void out(Outputalbe data) { | |
System.out.println(data.output()); | |
} | |
} |
しかし、既存のクラスに関してはそうはいかないので、ラッパークラスを
用意することになります。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.text.SimpleDateFormat; | |
import java.util.Calendar; | |
public class OutputableCalendar implements Outputalbe { | |
private final Calendar calendar; | |
public OutputableCalendar(Calendar calendar) { | |
super(); | |
this.calendar = calendar; | |
} | |
@Override | |
public String output() { | |
SimpleDateFormat format = new SimpleDateFormat("'Today is 'yyyy/MM/dd"); | |
return format.format(this.calendar.getTime()); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.Calendar; | |
import java.util.GregorianCalendar; | |
public class Display { | |
public static void main(String[] args) { | |
Display display = new Display(); | |
Calendar today = GregorianCalendar.getInstance(); | |
Outputalbe data = new OutputableCalendar(today); | |
display.out(data); //Today is 2013/01/01 | |
} | |
private void out(Outputalbe data) { | |
System.out.println(data.output()); | |
} | |
} |
呼び出し元も、新しいクラスを呼び出したりで面倒くさい。
Javaという言語は面倒臭いですん。
さて、Rubyではもっと柔軟な感じにいけて、クラスの定義を
コードの途中で再開させることができるのです。
まずは、自前のクラスに対しての実装。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require "./Profile.rb" | |
def display(data) | |
puts data.output | |
end | |
profile = Profile.new("numa08", 24) | |
display(profile) #Hey I am numa08 and , I'm 24 old. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Profile | |
def initialize(name, age) | |
@name = name | |
@age = age | |
end | |
def output | |
"Hell, I am #{@name} , and I'm #{@age} old." | |
end | |
end |
そして、既存のクラスの拡張。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Time | |
def output | |
strftime("Today is %Y/%m/%d") | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def display(data) | |
puts data.output | |
end | |
today = Time.now | |
display(today) #Today is 2013/01/01 |
Rubyって便利。
そして、最後にScala。暗黙的変換のimplicitキーワードを使ったメソッドを
用意することで、コンパイラが自動的に適した型に変換するメソッドを呼び出して
くれるのです。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
trait Outputable { | |
def output:String | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Profile(name:String, age:Int) extends Outputable{ | |
override def output = { | |
"Hey I am " + name + " and , I'm " + age + " old." | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def output(data:Outputable) = { | |
println(data.output) | |
} | |
val me = new Profile("numa08", 24) | |
output(me) //Hey I am numa08 and , I'm 24 old. |
implicitを使って変換を行う例。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.text.SimpleDateFormat; | |
import java.util.Calendar; | |
class OutputableCalendar(calendar:Calendar) extends Outputable{ | |
override def output = { | |
val format = new SimpleDateFormat("'Today is 'yyyy/MM/dd") | |
format.format(calendar.getTime) | |
} | |
} | |
implicit def toOutput(calendar:Calendar) = new OutputableCalendar(calendar) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.text.SimpleDateFormat; | |
import java.util.Calendar; | |
def output(data:Outputable) = { | |
println(data.output) | |
} | |
val today = Calendar.getInstance | |
output(today) //Today is 2013/01/01 |
実に気持ちがいい。呼び出し元は、クラスの変換とか意識しなくていいんですよ。
ただ、Javaでも型変換にtoHoge()な実装をしない
コードをたくさん見てきたので、ちょっとアレ。
今年も、綺麗なコードを求めてがんばりますね。
さて、今回参考にした書籍は次。
あと、最近はPlay frameworkを使ってScalaを
勉強してます。