èè
ã«ã€ããŠïŒPavel Fatin㯠ã JetBrainsã® IntelliJ IDEAã®Scalaãã©ã°ã€ã³ã«åãçµãã§ããŸã ãã¯ããã«
ãã®èšäºã§ã¯ãå€å
žçãª
Scala èšèšãã¿ãŒã³ãã©ã®ããã«å®è£
ããããã®äŸã瀺ããŸãã
ãã®èšäºã®å
容ã¯ã
JavaDayã«ã³ãã¡ã¬ã³ã¹ã§ã®ç§ã®ãã¬ãŒã³ããŒã·ã§ã³ã®åºç€ãšãªããŸãïŒ
ãã¬ãŒã³ããŒã·ã§ã³ã®ã¹ã©ã€ã ïŒã
èšèšãã¿ãŒã³
ãã¶ã€ã³ãã¿ãŒã³ã¯ããœãããŠã§ã¢éçºã®äžè¬çãªåé¡ã«å¯Ÿããäžè¬çãªåå©çšå¯èœãªãœãªã¥ãŒã·ã§ã³ã§ãã èšèšãã¿ãŒã³ã¯ãç¹å®ã®åé¡ã解決ããããã«äœ¿çšããå®å
šãªã³ãŒãã§ã¯ãªããç¹å®ã®ããŒãºã«é©åãããå¿
èŠããããã³ãã¬ãŒãã«ãããŸããã èšèšãã¿ãŒã³ã¯ãã³ãŒãã®å¯èªæ§ãåäžãããéçºããã»ã¹ãã¹ããŒãã¢ããããã®ã«åœ¹ç«ã€å¹æçãªèšèšã®ãã¹ããã©ã¯ãã£ã¹ã§ãã
æ©èœèšèšãã¿ãŒã³
å€å
žçãªãã¶ã€ã³ãã¿ãŒã³ã¯ãªããžã§ã¯ãæåã§ãã ã¯ã©ã¹ãšãªããžã§ã¯ãéã®é¢ä¿ãšçžäºäœçšã瀺ããŸãã ãããã®ã¢ãã«ã¯ãçŽç²ãªé¢æ°åããã°ã©ãã³ã°ã§ã¯ããŸãé©çšã§ããŸããïŒã颿°åãèšèšãã¿ãŒã³ã«ã€ããŠã¯ã
Haskellã®Typeclassopediaããã³
Scalazãåç
§ããŠãã ããïŒã
èšèšãã¿ãŒã³ã¯ãããã°ã©ãã³ã°èšèªã«ãªãå¿
èŠãªæ§æèŠçŽ ã®ä»£ããã«ãªãå ŽåããããŸãã èšèªã«å¿
èŠãªæ©èœãããå Žåããã¿ãŒã³ãç°¡çŽ åãŸãã¯å®å
šã«åé€ã§ããŸãã
Scalaã®äžçã§ã¯ãã»ãšãã©ã®å€å
žçãªãã¿ãŒã³ã¯ã衚çŸåè±ããªæ§ææ§é ã䜿çšããŠå®è£
ãããŠããŸãã
Scalaã«ã¯ç¬èªã®è¿œå ãã¿ãŒã³ããããŸããããã®èšäºã§ã¯éçºè
éã®çžäºçè§£ã®éµã§ãããããå€å
žçãªãã¶ã€ã³ãã¿ãŒã³ã®ã¿ã説æããŸãã
ããã«æããäŸã¯ã
Scalaèšèªã®ãã«ãã¯ãŒã䜿çšããŠãã衚çŸçã«å®è£
ã§ãããšããäºå®ã«ããããããã
Javaå®è£
ã
Scalaå®è£
ã«ã©ã®ããã«é¢é£ããããããæç¢ºã«çè§£ããããã«ãåçŽã§æå¿«ãªãã®ãåªå
ããŠè€éãªããªãã¯ãåé¿ããããšããŸããã
èšèšãã¿ãŒã³ã®æŠèŠ
ãžã§ãã¬ãŒãã£ããã¶ã€ã³ãã¿ãŒã³ïŒ åµé çãã¿ãŒã³ ïŒïŒ
è¡åãã¿ãŒã³ïŒ
次ã«ãèšèšãã¿ãŒã³ã®å®è£
ãæäŸãããŸãïŒãã¹ãŠã®ã³ãŒãã¯
Githubãªããžããªã§å©çšå¯èœ
ã§ã ïŒã
èšèšãã¿ãŒã³ã®å®è£
å·¥å Žå·¥æ³
ãã¡ã¯ããªã¡ãœãããã¿ãŒã³
㯠ããªããžã§ã¯ããäœæããããã®ã€ã³ã¿ãŒãã§ã€ã¹ãæäŸããäœæãããªããžã§ã¯ãã®ã¯ã©ã¹ã«é¢ããæ±ºå®ãã«ãã»ã«åããããã«äœ¿çšãããŸãã
ãã®ãã¿ãŒã³ã䜿çšãããšã次ã®ããšãã§ããŸãã
- è€éãªãªããžã§ã¯ããäœæããããžãã¯ãçµã¿åãããŠã
- ã¯ã©ã¹ãéžæããŠãªããžã§ã¯ããäœæãã
- ãã£ãã·ã¥ãªããžã§ã¯ã
- å
±æãªãœãŒã¹ãžã®ã¢ã¯ã»ã¹ã調æŽããŸãã
Factory Methodãã¿ãŒã³ã®å€å
žçãªããŒãžã§ã³ãšã¯ãããã«ç°ãªã
Static Factory Methodãã¿ãŒã³ã®å®è£
ã«ã€ããŠã以äžã§èª¬æããŸã
ã ã
Javaã§ã¯ãã³ã³ã¹ãã©ã¯ã¿ãåŒã³åºãããšã«ããã
newæŒç®åã䜿çšããŠã¯ã©ã¹ãã€ã³ã¹ã¿ã³ã¹åããŸãã ãã³ãã¬ãŒããå®è£
ãããšããã³ã³ã¹ãã©ã¯ã¿ãçŽæ¥äœ¿çšããã®ã§ã¯ãªããç¹å¥ãªã¡ãœããã䜿çšããŠãªããžã§ã¯ããäœæããŸãã
public interface Animal {}
public class Dog implements Animal {}
public class Cat implements Animal {}
public class AnimalFactory { public static Animal createAnimal(String kind) { if ("cat".equals(kind)) { return new Cat(); } if ("dog".equals(kind)) { return new Dog(); } throw new IllegalArgumentException(); } }
ãã¿ãŒã³ã®äœ¿çšäŸã¯ãç¬ã®äœæã§ãã
Animal animal = AnimalFactory.createAnimal("dog");
ã³ã³ã¹ãã©ã¯ã¿ãŒã«å ããŠã
Scalaã¯ã³ã³ã¹ãã©ã¯ã¿ãŒã®åŒã³åºãã«äŒŒãç¹å¥ãªæ§ææ§æäœãæäŸããŸãããå®éã«ã¯äŸ¿å©ãªãã¡ã¯ããªãŒã¡ãœããã§ãã
trait Animal private class Dog extends Animal private class Cat extends Animal object Animal { def apply(kind: String) = kind match { case "dog" => new Dog() case "cat" => new Cat() } }
䜿çšäŸïŒ
Animal("dog")
ãã¡ã¯ããªã¡ãœããã¯ããããããã³ã³ãããªã³ãªããžã§ã¯ããã§å®çŸ©ãããŸã-åããœãŒã¹ãã¡ã€ã«ã§å®çŸ©ãããåãååã®ç¹å¥ãªã·ã³ã°ã«ãã³ãªããžã§ã¯ãããã®æ§æã¯ããªããžã§ã¯ãã®äœæããµãã¯ã©ã¹ã«å§ä»»ããããšãã§ããªããªãããããã¿ãŒã³ã®ãéçãå®è£
ã«å¶éãããŸãã
é·æïŒ
- åºæ¬ã¯ã©ã¹åãåå©çšããŸãã
- æšæºçãã€ç°¡æœã
- ãã¶ã€ããŒã®åŒã³åºããæãåºãããŸãã
çæïŒ
- ãéçããã¡ã¯ããªã¡ãœããã
é
å»¶åæå
é
å»¶åæåã¯ã
é
å»¶ã³ã³ãã¥ãŒãã£ã³ã°ã®ç¹æ®ãªã±ãŒã¹ã§ãã ãã®ãã¿ãŒã³ã¯ãæåã®ã¢ã¯ã»ã¹ã§ã®ã¿å€ïŒãŸãã¯ãªããžã§ã¯ãïŒãåæåããããã®ã¡ã«ããºã ãæäŸãããããã³ã¹ãã®ãããèšç®ãå»¶æïŒãŸãã¯åé¿ïŒã§ããŸãã
éåžžã
Javaã§ãã¿ãŒã³ãå®è£
ããå ŽåãåæåãããŠããªãç¶æ
ã瀺ãããã«ç¹å¥ãª
nullå€ã䜿çšãããŸãã ãã ãã
nullãæå¹ãªåæåå€ã§ããå Žåãåæåç¶æ
ã瀺ãããã«è¿œå ã®ãã©ã°ãå¿
èŠã§ãã ãã«ãã¹ã¬ããã³ãŒãã§ã¯ãç«¶åç¶æ
ãåé¿ããããã«ããã®ãã©ã°ãžã®ã¢ã¯ã»ã¹ãåæããå¿
èŠããããŸãã åæãæ¹åããã«ã¯ãããã«ãã§ãã¯ããã¯ã䜿çšã§ããŸããããã«ãããã³ãŒããããã«è€éã«ãªããŸãã
private volatile Component component; public Component getComponent() { Component result = component; if (result == null) { synchronized(this) { result = component; if (result == null) { component = result = new Component(); } } } return result; }
䜿çšäŸïŒ
Component component = getComponent();
Scalaã¯ãããç°¡æœãªçµã¿èŸŒã¿ã¡ã«ããºã ãæäŸããŸãã
lazy val x = { print("(computing x) ") 42 }
䜿çšäŸïŒ
print("x = ") println(x)
Scalaã®é
å»¶åæåã¯ã
nullå€ã§ãããŸãæ©èœã
ãŸã ã ä¿çäžã®å€ãžã®ã¢ã¯ã»ã¹ã¯ã¹ã¬ããã»ãŒãã§ãã
é·æ
- çãæ§æã
- é
å»¶å€ã¯ãã«å€ã«ã䜿çšã§ããŸãã
- ä¿çäžã®å€ã¯ã¹ã¬ããã»ãŒãã§ãã
çæ
- åæåã®å¶åŸ¡ãå°ãªãã
ã·ã³ã°ã«ãã³ïŒã·ã³ã°ã«ãã³ïŒ
ã·ã³ã°ã«ãã³ãã¿ãŒã³ã¯ãã¯ã©ã¹ã®ã€ã³ã¹ã¿ã³ã¹ã®æ°ãã€ãŸã1ã€ã®ãªããžã§ã¯ãã®ã¿ãå¶éããã¡ã«ããºã ãæäŸãããã®ãªããžã§ã¯ããžã®ã°ããŒãã«ã¢ã¯ã»ã¹ãã€ã³ããæäŸããŸãã ãããã
Javaã§æãåºãç¥ãããŠãããã¶ã€ã³ãã¿ãŒã³ã§ããã·ã³ã°ã«ãã³ã¯ãèšèªã«å¿
èŠãªæ§æããªãããšã®æç¢ºãªå
åã§ãã
Javaã«ã¯ããªããžã§ã¯ãïŒã¯ã©ã¹ã€ã³ã¹ã¿ã³ã¹ïŒãšã®éä¿¡ããªãããšã瀺ãç¹å¥ãªããŒã¯ãŒã
staticããããŸãã ãã®ããŒã¯ãŒãã§ããŒã¯ãããã¡ãœããã¯ãç¶æ¿äžã«ãªãŒããŒã©ã€ãã§ããŸããã ãã®ãããªæŠå¿µã¯ããã¹ãŠããªããžã§ã¯ãã§ãããšããåºæ¬çãªOOPååã«åããŸãã
ãã®ããããã®ãã¿ãŒã³ã¯ãäœããã®ã€ã³ã¿ãŒãã§ã€ã¹ã®ã°ããŒãã«å®è£
ãžã®ã¢ã¯ã»ã¹ãå¿
èŠãªå Žåã«äœ¿çšãããŸãïŒããããåæåãé
å»¶ããŸãïŒã
public class Cat implements Runnable { private static final Cat instance = new Cat(); private Cat() {} public void run() {
䜿çšäŸïŒ
Cat.getInstance().run()
ãã ãããã¿ãŒã³ã®ããçµéšè±å¯ãªå®è£
ïŒåæåã®é
å»¶ã䌎ãïŒã¯ã倧éã®ã³ãŒãã§èšè¿°ãããããŸããŸãªçš®é¡ã®ãšã©ãŒïŒããšãã°ã
ãäºéãã§ãã¯ä»ããããã¯ã ïŒã«ã€ãªããå¯èœæ§ããããŸãã
Scalaã¯ããã®ãã¿ãŒã³ãå®è£
ããããã®ã³ã³ãã¯ããªã¡ã«ããºã ãæäŸããŸãã
object Cat extends Runnable { def run() {
䜿çšäŸïŒ
Cat.run()
Scalaã§ã¯ããªããžã§ã¯ãã¯ã¯ã©ã¹ãŸãã¯ã€ã³ã¿ãŒãã§ãŒã¹ããã¡ãœãããç¶æ¿ã§ããŸãã ãªããžã§ã¯ããåç
§ã§ããŸãïŒçŽæ¥ãŸãã¯ã¬ã¬ã·ãŒã€ã³ã¿ãŒãã§ã€ã¹çµç±ïŒã
Scalaã§ã¯ããªããžã§ã¯ãã¯èŠæ±ã«å¿ããŠé
å»¶ããŠåæåãããŸãã
é·æ
- ééçãªå®è£
ã
- ã³ã³ãã¯ããªæ§æã
- åæåã®é
å»¶ã
- ã¹ã¬ããã»ãŒãã
çæ
- åæåã®å¶åŸ¡ãå°ãªãã
ã¢ããã¿ãŒ
ã¢ããã¿ãã¿ãŒã³ã¯ãããã€ã³ã¿ãŒãã§ã€ã¹ãå¥ã®ã€ã³ã¿ãŒãã§ã€ã¹ã«å€æããã¡ã«ããºã ãæäŸãããããã®ç°ãªãã€ã³ã¿ãŒãã§ã€ã¹ãå®è£
ããã¯ã©ã¹ã飿ºããŠåäœã§ããããã«ããŸãã
ã¢ããã¿ã¯ãæ¢åã®ã³ã³ããŒãã³ããçµ±åããã®ã«äŸ¿å©ã§ãã
Javaã§ã®å®è£
ã§ã¯ãã³ãŒãã§æç€ºçã«äœ¿çšãããã©ãããŒã¯ã©ã¹ãäœæããŸãã
public interface Log { void warning(String message); void error(String message); } public final class Logger { void log(Level level, String message) { } } public class LoggerToLogAdapter implements Log { private final Logger logger; public LoggerToLogAdapter(Logger logger) { this.logger = logger; } public void warning(String message) { logger.log(WARNING, message); } public void error(String message) { logger.log(ERROR, message); } }
䜿çšäŸïŒ
Log log = new LoggerToLogAdapter(new Logger());
Scalaã«ã¯ãã€ã³ã¿ãŒãã§ãŒã¹ãé©åãããããã®ç¹å¥ãªçµã¿èŸŒã¿ã¡ã«ããºã ïŒæé»çãªã¯ã©ã¹ïŒããããŸãã
trait Log { def warning(message: String) def error(message: String) } final class Logger { def log(level: Level, message: String) { } } implicit class LoggerToLogAdapter(logger: Logger) extends Log { def warning(message: String) { logger.log(WARNING, message) } def error(message: String) { logger.log(ERROR, message) } }
䜿çšäŸïŒ
val log: Log = new Logger()
Logã¿ã€ãã®äœ¿çšãæ³å®ãããŠããŸããã
Scalaã³ã³ãã€ã©ãŒã¯
Loggerã¯ã©ã¹ãã€ã³ã¹ã¿ã³ã¹åããã¢ããã¿ãŒã§ã©ããããŸãã
é·æ
- ééçãªå®è£
ã
- ã³ã³ãã¯ããªæ§æã
çæ
- IDEã䜿çšããã«æ··ä¹±ããå¯èœæ§ããããŸãã
ãã³ã¬ãŒã¿
ãã³ã¬ãŒã¿ãã¿ãŒã³ã¯ãåãã¯ã©ã¹ã®ä»ã®ã€ã³ã¹ã¿ã³ã¹ã«åœ±é¿ãäžããã«ãªããžã§ã¯ãã®æ©èœãæ¡åŒµããããã«äœ¿çšãããŸãã ãã³ã¬ãŒã¿ã¯ãç¶æ¿ã®æè»ãªä»£æ¿ææ®µãæäŸããŸãã ãã®ãã¿ãŒã³ã¯ãæ©èœãæ¡åŒµããç¬ç«ããæ¹æ³ãããã€ããããããããä»»æã«çµã¿åãããããšãã§ããå Žåã«äœ¿çšãããšäŸ¿å©ã§ãã
Javaã§å®è£
ãããšãããŒã¹ã€ã³ã¿ãŒãã§ã€ã¹ãç¶æ¿ããå
ã®ã¯ã©ã¹ãã©ããããæ°ãããã³ã¬ãŒã¿ã¯ã©ã¹ãå®çŸ©ãããè€æ°ã®ãã³ã¬ãŒã¿ããã¹ãã§ããŸãã äžéãã³ã¬ãŒã¿ãŒã¯ã©ã¹ã¯ãããã€ãã®ã¡ãœãããå§ä»»ããããã«ãã䜿çšãããŸãã
public interface OutputStream { void write(byte b); void write(byte[] b); } public class FileOutputStream implements OutputStream { } public abstract class OutputStreamDecorator implements OutputStream { protected final OutputStream delegate; protected OutputStreamDecorator(OutputStream delegate) { this.delegate = delegate; } public void write(byte b) { delegate.write(b); } public void write(byte[] b) { delegate.write(b); } } public class BufferedOutputStream extends OutputStreamDecorator { public BufferedOutputStream(OutputStream delegate) { super(delegate); } public void write(byte b) {
䜿çšäŸïŒ
new BufferedOutputStream(new FileOutputStream("foo.txt"));
åãç®æšãéæããããã«ã
Scalaã¯ç¹å®ã®å®è£
ã«çžãããããšãªããã€ã³ã¿ãŒãã§ãŒã¹ã¡ãœããããªãŒããŒã©ã€ãããçŽæ¥çãªæ¹æ³ãæäŸããŸãã
trait OutputStream { def write(b: Byte) def write(b: Array[Byte]) } class FileOutputStream(path: String) extends OutputStream { } trait Buffering extends OutputStream { abstract override def write(b: Byte) {
䜿çšäŸïŒ
new FileOutputStream("foo.txt") with Buffering
å§ä»»ã¯ã³ã³ãã€ã«æã«éçã«èšå®ãããŸããããªããžã§ã¯ãã®äœææã«ãã³ã¬ãŒã¿ãä»»æã«çµã¿åãããããšãã§ããéããéåžžããã§ååã§ãã
æ§æããŒã¹ã®å®è£
ãšã¯ç°ãªããScalaã®ã¢ãããŒãã¯ãªããžã§ã¯ãã®IDãä¿æãããããè£
食ããããªããžã§ã¯ãã§
equalsãå®å
šã«äœ¿çšã§ããŸãã
Scalaã§ã¯ããã®è£
食ã¢ãããŒãã¯
Stackable Trait PatternãšåŒã°ããŸãã
é·æ
- ééçãªå®è£
ã
- ã³ã³ãã¯ããªæ§æã
- ãªããžã§ã¯ãã®èå¥ãä¿åãããŸãã
- æç€ºçãªå§ä»»ã®æ¬ åŠã
- äžéãã³ã¬ãŒã¿ãŒã¯ã©ã¹ã®æ¬ åŠã
çæ
- éçãã€ã³ãã£ã³ã°ã
- ãã©ã¡ãŒã¿ãŒãªãã®ã³ã³ã¹ãã©ã¯ã¿ãŒã
å€ãªããžã§ã¯ã
å€ãªããžã§ã¯ãã¯å°ããªäžå€ã®å€ã§ãã ãã¹ãŠã®ãã£ãŒã«ããçããå Žåãå€ãªããžã§ã¯ãã¯çãããªããŸãã å€ãªããžã§ã¯ãã¯ãæ°å€ãæ¥ä»ãè²ãªã©ã衚ãããã«åºã䜿çšãããŠããŸãã äŒæ¥ã¢ããªã±ãŒã·ã§ã³ã§ã¯ããã®ãããªãªããžã§ã¯ãã¯ããã»ã¹éã®çžäºäœçšã®ããã®
DTOãªããžã§ã¯ããšããŠäœ¿çšãã
ãŸããäžå€ã§ãããããå€ãªããžã§ã¯ãã¯ãã«ãã¹ã¬ããããã°ã©ãã³ã°ã§äŸ¿å©ã§ãã
Javaã«ã¯å€ãªããžã§ã¯ããäœæããããã®ç¹å¥ãªæ§æ
ã¯ãããŸãããã代ããã«ãã³ã³ã¹ãã©ã¯ã¿ãŒãã²ãã¿ãŒã¡ãœãããããã³è¿œå ã®ã¡ãœããïŒequalsãhashCodeãtoStringïŒã§ã¯ã©ã¹ãäœæãããŸãã
public class Point { private final int x, y; public Point(int x, int y) { this.x = x; this.y = y; } public int getX() { return x; } public int getY() { return y; } public boolean equals(Object o) {
䜿çšäŸïŒ
Point point = new Point(1, 2)
Scalaã§ã¯ãã¿ãã«ãŸãã¯ã±ãŒã¹ã¯ã©ã¹ã䜿çšããŠå€ãªããžã§ã¯ãã宣èšã§ããŸãã å¥ã®ã±ãŒã¹ã¯ã©ã¹ãäžèŠãªå Žåã¯ãã¿ãã«ã䜿çšã§ããŸãã
val point = (1, 2)
ã¿ãã«ã¯ãããŸããŸãªã¿ã€ãã®åºå®æ°ã®èŠçŽ ãå«ãããšãã§ããäºåå®çŸ©ãããäžå€ã®ãã³ã¬ã¯ã·ã§ã³ãã§ãã ã¿ãã«ã¯ãã³ã³ã¹ãã©ã¯ã¿ãŒãã²ãã¿ãŒã¡ãœãããããã³ãã¹ãŠã®ãã«ããŒã¡ãœãããæäŸããŸãã
type Point = (Int, Int)
ããã§ãèå¥ã¯ã©ã¹ãå¿
èŠãªå ŽåããŸãã¯ããŒã¿èŠçŽ ã®ããããããããååãå¿
èŠãªå Žåã¯ãã±ãŒã¹ã¯ã©ã¹ãå®çŸ©ã§ããŸãã
case class Point(x: Int, y: Int) val point = Point(1, 2)
ã±ãŒã¹ã¯ã©ã¹ã¯ãã¯ã©ã¹ã³ã³ã¹ãã©ã¯ã¿ãŒãã©ã¡ãŒã¿ãŒã®ããããã£ãäœæããŸãã ããã©ã«ãã§ã¯ãã±ãŒã¹ã¯ã©ã¹ã¯äžå€ã§ãã ã¿ãã«ãšåæ§ã«ãå¿
èŠãªãã¹ãŠã®ã¡ãœãããèªåçã«æäŸããŸãã ããã«ãã±ãŒã¹ã¯ã©ã¹ã¯æå¹ãªã¯ã©ã¹ã§ããã€ãŸããã±ãŒã¹ã¯ã©ã¹ã¯éåžžã®ã¯ã©ã¹ã®ããã«æäœã§ããŸãïŒããšãã°ãç¶æ¿ããŸãïŒã
é·æ
- ã³ã³ãã¯ããªæ§æã
- å®çŸ©æžã¿ã®èšèªæ§æäœã¯ã¿ãã«ã§ãã
- çµã¿èŸŒã¿ã®å¿
èŠãªã¡ãœããã
çæ
æ¬ åžããŠããŸãã
ãã«ãªããžã§ã¯ã
nullãªããžã§ã¯ãã¯ã
ãªããžã§ã¯ããååšããªãããšã§ãäžç«ã®ãéã¢ã¯ãã£ãããªåäœãå®çŸ©ããŸãã
ãã®ã¢ãããŒãã¯ã䜿çšåã«ãªã³ã¯ãæç€ºçã«ç¢ºèªããå¿
èŠããªãããã
nullãªã³ã¯ã®äœ¿çšãããåªå
ãããŸãã
Javaã§ã¯ããã¿ãŒã³ã®å®è£
ã¯ãã空ã®ãã¡ãœãããæã€ç¹å¥ãªãµãã¯ã©ã¹ãäœæããããšã§ãã
public interface Sound { void play(); } public class Music implements Sound { public void play() { } } public class NullSound implements Sound { public void play() {} } public class SoundSource { public static Sound getSound() { return available ? music : new NullSound(); } } SoundSource.getSound().play();
ããã§ã次ã®
playã¡ãœããã®åŒã³åºãã®åã«
getSoundã¡ãœããã
åŒã³åºããããšãã«åä¿¡ãããªã³ã¯ã確èªããå¿
èŠããªããªããŸããã ããã«ãNullãªããžã§ã¯ããã·ã³ã°ã«ãã³ã«ããããšãã§ããŸãã
Scalaã¯ããªãã·ã§ã³ã®å€ã®ãã³ã³ããããšããŠäœ¿çšã§ããäºåå®çŸ©ããã
Optionã¿ã€ãã䜿çšããŠãåæ§ã®ã¢ãããŒãã䜿çšããŸãã
trait Sound { def play() } class Music extends Sound { def play() { } } object SoundSource { def getSound: Option[Sound] = if (available) Some(music) else None } for (sound <- SoundSource.getSound) { sound.play() }
é·æ
- å®çŸ©æžã¿ã®ã¿ã€ãã
- æç€ºçãªãªãã·ã§ã³ã
- ãªãã·ã§ã³ã®å€ãæäœããããã®çµã¿èŸŒã¿èšèªæ§é ã
çæ
æŠç¥
æŠç¥ãã¿ãŒã³ã¯ãã«ãã»ã«åãããã¢ã«ãŽãªãºã ã®ãã¡ããªãå®çŸ©ããããã䜿çšããã¯ã©ã€ã¢ã³ãã«åœ±é¿ãäžããããšãªããç¬èªã«ã¢ã«ãŽãªãºã ã倿Žã§ããŸãã å®è¡æã«ã¢ã«ãŽãªãºã ã倿Žããå¿
èŠãããå Žåããã¿ãŒã³ã䜿çšãããšäŸ¿å©ã§ãã
Javaã§ã¯ããã¿ãŒã³ã¯éåžžãããŒã¹ã€ã³ã¿ãŒãã§ã€ã¹ãç¶æ¿ããã¯ã©ã¹ã®éå±€ãäœæããããšã§å®è£
ãããŸãã
public interface Strategy { int compute(int a, int b); } public class Add implements Strategy { public int compute(int a, int b) { return a + b; } } public class Multiply implements Strategy { public int compute(int a, int b) { return a * b; } } public class Context { private final Strategy strategy; public Context(Strategy strategy) { this.strategy = strategy; } public void use(int a, int b) { strategy.compute(a, b); } } new Context(new Multiply()).use(2, 3);
Scalaã«ã¯äžæµã®é¢æ°ãããããããã¿ãŒã³ã®æŠå¿µã¯èšèªèªäœã䜿çšããŠå®è£
ãããŸãã
type Strategy = (Int, Int) => Int class Context(computer: Strategy) { def use(a: Int, b: Int) { computer(a, b) } } val add: Strategy = _ + _ val multiply: Strategy = _ * _ new Context(multiply).use(2, 3)
æŠç¥ã¢ã«ãŽãªãºã ã«è€æ°ã®ã¡ãœãããå«ãŸããå Žåãã±ãŒã¹ã¯ã©ã¹ãŸãã¯ã¿ãã«ã䜿çšããŠã¡ãœãããã°ã«ãŒãåã§ããŸãã
é·æ
- ã³ã³ãã¯ããªæ§æã
çæ
ã³ãã³ã
ãã¿ãŒã³ã³ãã³ã㯠ããªã¢ãŒããã€ã³ãã§ã¡ãœãããåŒã³åºãããã«å¿
èŠãªæ
å ±ãã«ãã»ã«åããããã«äœ¿çšãããŸãã ãã®æ
å ±ã«ã¯ãã¡ãœããã®ååãã¡ãœãããå±ãããªããžã§ã¯ããããã³ã¡ãœãããã©ã¡ãŒã¿ãŒã®å€ãå«ãŸããŸãã
Javaã§ã¯ããã¿ãŒã³
ã®å®è£
ã¯åŒã³åºãããªããžã§ã¯ãã«ã©ããããããšã§ãã
public class PrintCommand implements Runnable { private final String s; PrintCommand(String s) { this.s = s; } public void run() { System.out.println(s); } } public class Invoker { private final List<Runnable> history = new ArrayList<>(); void invoke(Runnable command) { command.run(); history.add(command); } } Invoker invoker = new Invoker(); invoker.invoke(new PrintCommand("foo")); invoker.invoke(new PrintCommand("bar"));
Scalaã«ã¯ãé
å»¶ã³ã³ãã¥ãŒãã£ã³ã°çšã®ç¹å¥ãªã¡ã«ããºã ããããŸãã
object Invoker { private var history: Seq[() => Unit] = Seq.empty def invoke(command: => Unit) {
ããã«ãããä»»æã®åŒãŸãã¯ã³ãŒããããã¯ããªããžã§ã¯ã颿°ã«å€æã§ããŸãã
printlnã¡ãœããã®åŒã³åºãã¯ãã¡ãœããã®åŒã³åºãå
ã§è¡ããããã®åŸã
å±¥æŽã·ãŒã±ã³ã¹ã«ä¿åãããŸãã
é·æ
- ã³ã³ãã¯ããªæ§æã
çæ
責任ã®é£é
責任ã®é£éãã¿ãŒã³ã«ããããªã¯ãšã¹ãã®éä¿¡è
ãšåä¿¡è
ãåé¢ãããè€æ°ã®ãšã³ãã£ãã£ããªã¯ãšã¹ããåŠçã§ããããã«ãªããŸãã ãªã¯ãšã¹ãã¯ãããã€ãã®ãªããžã§ã¯ããåŠçãããŸã§ãã§ãŒã³ã«ãã£ãŠåŠçãããŸãã
å
žåçãªãã¿ãŒã³å®è£
ã§ã¯ããã§ãŒã³å
ã®åãªããžã§ã¯ãã¯ããŒã¹ã€ã³ã¿ãŒãã§ã€ã¹ãç¶æ¿ãããã§ãŒã³å
ã®æ¬¡ã®åŠçãªããžã§ã¯ããžã®ãªãã·ã§ã³ã®åç
§ãå«ã¿ãŸãã åãªããžã§ã¯ãã«ã¯ããªã¯ãšã¹ããåŠçããïŒããã³å²ã蟌ã¿åŠçããïŒãããã§ãŒã³å
ã®æ¬¡ã®ãã³ãã©ã«ãªã¯ãšã¹ããæž¡ãæ©äŒãäžããããŸãã
public abstract class EventHandler { private EventHandler next; void setNext(EventHandler handler) { next = handler; } public void handle(Event event) { if (canHandle(event)) doHandle(event); else if (next != null) next.handle(event); } abstract protected boolean canHandle(Event event); abstract protected void doHandle(Event event); } public class KeyboardHandler extends EventHandler {
䜿çšäŸïŒ
KeyboardHandler handler = new KeyboardHandler(); handler.setNext(new MouseHandler());
Scalaã¯ããã®ãããªåé¡ã解決ããããã®ããæŽç·Žãããã¡ã«ããºã ãã€ãŸã
éšå颿°ãæäŸããŸã ã éšå颿°ã¯ãåŒæ°ã®å¯èœãªå€ã®ãµãã»ããã§å®çŸ©ããã颿°ã§ãã
isDefinedAtãš
applyã¡ãœããã®çµã¿åããã䜿çšããŠãã§ãŒã³ãæ§ç¯ã§ããŸããã
getOrElseã¡ãœããã䜿çšããæ¹ãé©åã§ãã
case class Event(source: String) type EventHandler = PartialFunction[Event, Unit] val defaultHandler: EventHandler = PartialFunction(_ => ()) val keyboardHandler: EventHandler = { case Event("keyboard") => } def mouseHandler(delay: Int): EventHandler = { case Event("mouse") => }
keyboardHandler.orElse(mouseHandler(100)).orElse(defaultHandler)
ãæªå®çŸ©ãã€ãã³ãã§ã®ãšã©ãŒãåé¿ããããã«ã
ããã§
defaultHandlerã䜿çšãããããšã«æ³šæããããšãéèŠã§ãã
é·æ
- ã³ã³ãã¯ããªæ§æã
- çµã¿èŸŒã¿ã®èšèªæ§é ã
çæ
äŸåæ§æ³šå
¥
äŸåé¢ä¿æ³šå
¥ãã¿ãŒã³ã¯ãããŒãã³ãŒãã£ã³ã°ãããäŸåé¢ä¿ãåé¿ããå®è¡æãŸãã¯ã³ã³ãã€ã«æã«äŸåé¢ä¿ã眮ãæããŸãã ãã¿ãŒã³ã¯ã
å¶åŸ¡ã®
å転ïŒIoCïŒã®ç¹æ®ãªã±ãŒã¹ã§ãã
äŸåæ§æ³šå
¥ã¯ãã¢ããªã±ãŒã·ã§ã³å
ã®ç¹å®ã®ã³ã³ããŒãã³ãã®ããŸããŸãªå®è£
ããéžæããããããŸãã¯
åäœãã¹ãçšã® æš¡æ¬ã³ã³ããŒãã³ããæäŸããããã«äœ¿çšãããŸãã
IoCã³ã³ãããŒã®äœ¿çšã«å ããŠããã®ãã¿ãŒã³ã
Javaã§å®è£
ããæãç°¡åãªæ¹æ³ã¯ãã³ã³ã¹ãã©ã¯ã¿ãŒãã©ã¡ãŒã¿ãŒã䜿çšããŠãã€ã³ã¿ãŒãã§ã€ã¹ã®ç¹å®ã®å®è£
ïŒã¯ã©ã¹ããã®äœæ¥ã§äœ¿çšããïŒãæž¡ãããšã§ãã
public interface Repository { void save(User user); } public class DatabaseRepository implements Repository { } public class UserService { private final Repository repository; UserService(Repository repository) { this.repository = repository; } void create(User user) {
æ§æ
ïŒãHAS-AãïŒãšç¶æ¿
ïŒãIS-AãïŒã«å ã㊠ã
Scalaã¯ç¹å¥ãªçš®é¡ã®ãªããžã§ã¯ãé¢ä¿ãæäŸããŸã-
èªå·±ã¿ã€ãã®æ³šéã§è¡šçŸãããèŠä»¶
ïŒãREQUIRES-AãïŒ ã
èªå·±åã䜿çšãããšãç¶æ¿ãé©çšââããã«ãªããžã§ã¯ãã«è¿œå ã®åãæå®ã§ããŸãã
ç¹æ§ãšãšãã«
èªå·±å泚éã䜿çšããŠãäŸåæ§æ³šå
¥ãã¿ãŒã³ãå®è£
ã§ããŸãã
trait Repository { def save(user: User) } trait DatabaseRepository extends Repository { } trait UserService { self: Repository =>
ãã®æ¹æ³è«ã®å®å
šãªå®è£
ã¯ã
Cakeãã¿ãŒã³ãšããŠç¥ãããŠã
ãŸã ã ãã ããããããã¿ãŒã³ãå®è£
ããå¯äžã®æ¹æ³ã§ã¯ãªãã
Scalaã«äŸåæ§æ³šå
¥ãã¿ãŒã³ãå®è£
ããä»ã®å€ãã®æ¹æ³ããããŸãã
Scalaã§ã®
ç¹æ§ã® ãæ··åã
ã¯éçã§ãããã³ã³ãã€ã«æã«çºçããããšãæãåºããŠãã ããã ãã ããå®éã«ã¯ãæ§æã®å€æŽã¯ããã»ã©é »ç¹ã«ã¯å¿
èŠãããŸããããŸããã³ã³ãã€ã«æ®µéã§ã®éçæ€èšŒã®è¿œå ã®å©ç¹ã«ã¯ãXMLæ§æããã倧ããªå©ç¹ããããŸãã
é·æ
- ééçãªå®è£
ã
- ã³ã³ãã¯ããªæ§æã
- ã³ã³ãã€ã«æã®éçãã§ãã¯ã
çæ
- ã³ã³ãã€ã«æ®µéã§ã®æ§æã
- æ§æãåé·ã«ãªãå ŽåããããŸãã
ãããã«
ãã®ãã¢ãã
Javaããã°ã©ããŒã
Scalaæ§æãçè§£ãã
Scalaããã°ã©ããŒãç¹å®ã®èšèªã³ã³ã¹ãã©ã¯ããããç¥ãããŠããæœè±¡æŠå¿µã«ãããã³ã°ã§ããããã«ããããšã§ã2ã€ã®èšèªéã®ã®ã£ãããåããããšãé¡ã£ãŠããŸãã