SlideShare a Scribd company logo
1 of 135
SCALA
        FOR
JAVA PROGRAMMERS
AGENDA
   1. Object orientation (OO)                     2. Functional programming (FP)

1.1 Every value is an object                      2.1   Every function is a value
1.2 Mixin-based composition with traits           2.2   Anonymous functions
1.3 Self-type annotations                         2.3   Higher-order functions
1.4 Structural typing                             2.4   Closures
1.5 Local type inference                          2.5   Currying
1.6 Static type system                            2.6   Immutability
1.7 Generic classes                               2.7   For comprehensions
1.8 Variance annotations                          2.8   Algebraic data types
1.9 Upper and lower type bounds                   2.9   Pattern matching
1.10 Inner classes and abstract types as object
members                                           3. Practice
1.12 Compound types
1.13 Explicitly typed self references             3.1 Square roots using Newtons method
1.14 Views, and polymorphic methods.              3.2 Finding fixed points
Scala For Java Programmers
WHAT WE (REALLY) WANT
      YOU TO LEARN:

•A   Java to Scala conversion is easy
• Scala   brings a lot of new possibilities
• You don’t have to understand all new possibilities
 to start with
JAVA ➟ SCALA
LET’S START WITH A WARM-UP
OUR ALL JAVA MAIN
                                                 Defined in Java

public static void main(String[] args) {


         JobFactory factory = new JdbcJobFactory();

         JobControl control = new JobControl(factory);

         ...
}
PROJECT LAYOUT


   Java
Application
 Module
PROJECT LAYOUT


   Java             Java
Application        Module
PROJECT LAYOUT


   Java             Scala       Java
Application        Module      Module
PROJECT LAYOUT

                   Job.java
   Java             Scala       Java
Application        Module      Module
PROJECT LAYOUT

                   Job.scala
   Java             Scala       Java
Application        Module      Module
public class Job {
	 private String name;
	 private List<Step> steps;
	 private Map<String, Object> args;

	   public Map<String, Object> getArgs() {
	   	 return args;
	   }
	   public void setArgs(Map<String, Object> args) {
	   	 this.args = args;
	   }
	   public List<Step> getSteps() {
	   	 return steps;
	   }
	   public void setSteps(List<Step> steps) {
	   	 this.steps = steps;
	   }
	   public String getName() {
	   	 return name;
	   }
	   public void setName(String name) {
	   	 this.name = name;
	   }
}
public class Job {
	 private String name;                                    Make it compile
	 private List<Step> steps;
	 private Map<String, Object> args;                   •Public is default
	   public Map<String, Object> getArgs() {
                                                      •Variables are
	   	 return args;                                     declared with var
	   }
	   public void setArgs(Map<String, Object> args) {   •Types after identifier
                                                      •Generics with []
	   	 this.args = args;
	   }
	
	
    public List<Step> getSteps() {
    	 return steps;                                   •Functions declared
	
	
    }
    public void setSteps(List<Step> steps) {
                                                       with def
	
	
    	 this.steps = steps;
    }
                                                      •= {...}
	
	
    public String getName() {
    	 return name;
                                                      •void ≈ Unit
	   }                                                 •initialize var
	   public void setName(String name) {
	   	 this.name = name;
	   }
}
class Job {
	 private String name;                             Make it compile
	 private List<Step> steps;
	 private Map<String, Object> args;            •Public is default
	   Map<String, Object> getArgs() {
                                               •Variables are
	   	 return args;                              declared with var
	   }
	   void setArgs(Map<String, Object> args) {   •Types after identifier
                                               •Generics with []
	   	 this.args = args;
	   }
	
	
    List<Step> getSteps() {
    	 return steps;                            •Functions declared
	
	
    }
    void setSteps(List<Step> steps) {
                                                with def
	
	
    	 this.steps = steps;
    }
                                               •= {...}
	
	
    String getName() {
    	 return name;
                                               •void ≈ Unit
	   }                                          •initialize var
	   void setName(String name) {
	   	 this.name = name;
	   }
}
class Job {
	 private String name;                             Make it compile
	 private List<Step> steps;
	 private Map<String, Object> args;            •Public is default
	   Map<String, Object> getArgs() {
                                               •Variables are
	   	 return args;                              declared with var
	   }
	   void setArgs(Map<String, Object> args) {   •Types after identifier
                                               •Generics with []
	   	 this.args = args;
	   }
	
	
    List<Step> getSteps() {
    	 return steps;                            •Functions declared
	
	
    }
    void setSteps(List<Step> steps) {
                                                with def
	
	
    	 this.steps = steps;
    }
                                               •= {...}
	
	
    String getName() {
    	 return name;
                                               •void ≈ Unit
	   }                                          •initialize var
	   void setName(String name) {
	   	 this.name = name;
	   }
}
class Job {
	 private String name;                             Make it compile
	 private List<Step> steps;
	 private Map<String, Object> args;            •Public is default
	   Map<String, Object> getArgs() {
                                               •Variables are
	   	 return args;                              declared with var
	   }
	   void setArgs(Map<String, Object> args) {   •Types after identifier
                                               •Generics with []
	   	 this.args = args;
	   }
	
	
    List<Step> getSteps() {
    	 return steps;                            •Functions declared
	
	
    }
    void setSteps(List<Step> steps) {
                                                with def
	
	
    	 this.steps = steps;
    }
                                               •= {...}
	
	
    String getName() {
    	 return name;
                                               •void ≈ Unit
	   }                                          •initialize var
	   void setName(String name) {
	   	 this.name = name;
	   }
}
class Job {
	 private var String name;                       Make it compile
	 private var List<Step> steps;
	 private var Map<String, Object> args;      •Public is default
	
	 Map<String, Object> getArgs() {
                                             •Variables are
	 	 return args;                              declared with var
	 }
	 void setArgs(Map<String, Object> args) {   •Types after identifier
                                             •Generics with []
	 	 this.args = args;
	 }
	 List<Step> getSteps() {
	 	 return steps;                            •Functions declared
	 }
	 void setSteps(List<Step> steps) {
                                              with def
	 	 this.steps = steps;
	 }
                                             •= {...}
	 String getName() {
	 	 return name;
                                             •void ≈ Unit
	 }                                          •initialize var
	 void setName(String name) {
	 	 this.name = name;
	 }
}
class Job {
	 private var String name;                       Make it compile
	 private var List<Step> steps;
	 private var Map<String, Object> args;      •Public is default
	
	 Map<String, Object> getArgs() {
                                             •Variables are
	 	 return args;                              declared with var
	 }
	 void setArgs(Map<String, Object> args) {   •Types after identifier
                                             •Generics with []
	 	 this.args = args;
	 }
	 List<Step> getSteps() {
	 	 return steps;                            •Functions declared
	 }
	 void setSteps(List<Step> steps) {
                                              with def
	 	 this.steps = steps;
	 }
                                             •= {...}
	 String getName() {
	 	 return name;
                                             •void ≈ Unit
	 }                                          •initialize var
	 void setName(String name) {
	 	 this.name = name;
	 }
}
class Job {
	 private var String name;                       Make it compile
	 private var List<Step> steps;
	 private var Map<String, Object> args;      •Public is default
	
	 Map<String, Object> getArgs() {
                                             •Variables are
	 	 return args;                              declared with var
	 }
	 void setArgs(Map<String, Object> args) {   •Types after identifier
                                             •Generics with []
	 	 this.args = args;
	 }
	 List<Step> getSteps() {
	 	 return steps;                            •Functions declared
	 }
	 void setSteps(List<Step> steps) {
                                              with def
	 	 this.steps = steps;
	 }
                                             •= {...}
	 String getName() {
	 	 return name;
                                             •void ≈ Unit
	 }                                          •initialize var
	 void setName(String name) {
	 	 this.name = name;
	 }
}
class Job {
	 private var name:String;                       Make it compile
	 private var steps:List<Step>;
	 private var args:Map<String, Object>;      •Public is default
	
	 getArgs():Map<String, Object> {
                                             •Variables are
	 	 return args;                              declared with var
	 }
	 setArgs(args:Map<String, Object>):void {   •Types after identifier
                                             •Generics with []
	 	 this.args = args;
	 }
   getSteps():List<Step> {
	 	 return steps;                            •Functions declared
	 }
	 setSteps(steps:List<Step>):void {
                                              with def
	 	 this.steps = steps;
	 }
                                             •= {...}
	 getName():String {
	 	 return name;
                                             •void ≈ Unit
	 }                                          •initialize var
	 setName(name:String):void {
	 	 this.name = name;
	 }
}
class Job {
	 private var name:String;                       Make it compile
	 private var steps:List<Step>;
	 private var args:Map<String, Object>;      •Public is default
	
	 getArgs():Map<String, Object> {
                                             •Variables are
	 	 return args;                              declared with var
	 }
	 setArgs(args:Map<String, Object>):void {   •Types after identifier
                                             •Generics with []
	 	 this.args = args;
	 }
   getSteps():List<Step> {
	 	 return steps;                            •Functions declared
	 }
	 setSteps(steps:List<Step>):void {
                                              with def
	 	 this.steps = steps;
	 }
                                             •= {...}
	 getName():String {
	 	 return name;
                                             •void ≈ Unit
	 }                                          •initialize var
	 setName(name:String):void {
	 	 this.name = name;
	 }
}
class Job {
	 private var name:String;                       Make it compile
	 private var steps:List<Step>;
	 private var args:Map<String, Object>;      •Public is default
	
	 getArgs():Map<String, Object> {
                                             •Variables are
	 	 return args;                              declared with var
	 }
	 setArgs(args:Map<String, Object>):void {   •Types after identifier
                                             •Generics with []
	 	 this.args = args;
	 }
   getSteps():List<Step> {
	 	 return steps;                            •Functions declared
	 }
	 setSteps(steps:List<Step>):void {
                                              with def
	 	 this.steps = steps;
	 }
                                             •= {...}
	 getName():String {
	 	 return name;
                                             •void ≈ Unit
	 }                                          •initialize var
	 setName(name:String):void {
	 	 this.name = name;
	 }
}
class Job {
	 private var name:String;                       Make it compile
	 private var steps:List[Step];
	 private var args:Map[String, Object];      •Public is default
	
	 getArgs():Map[String, Object] {
                                             •Variables are
	 	 return args;                              declared with var
	 }
	 setArgs(args:Map[String, Object]):void {   •Types after identifier
                                             •Generics with []
	 	 this.args = args;
	 }
   getSteps():List[Step] {
	 	 return steps;                            •Functions declared
	 }
	 setSteps(steps:List[Step]):void {
                                              with def
	 	 this.steps = steps;
	 }
                                             •= {...}
	 getName():String {
	 	 return name;
                                             •void ≈ Unit
	 }                                          •initialize var
	 setName(name:String):void {
	 	 this.name = name;
	 }
}
class Job {
	 private var name:String;                       Make it compile
	 private var steps:List[Step];
	 private var args:Map[String, Object];      •Public is default
	
	 getArgs():Map[String, Object] {
                                             •Variables are
	 	 return args;                              declared with var
	 }
	 setArgs(args:Map[String, Object]):void {   •Types after identifier
                                             •Generics with []
	 	 this.args = args;
	 }
   getSteps():List[Step] {
	 	 return steps;                            •Functions declared
	 }
	 setSteps(steps:List[Step]):void {
                                              with def
	 	 this.steps = steps;
	 }
                                             •= {...}
	 getName():String {
	 	 return name;
                                             •void ≈ Unit
	 }                                          •initialize var
	 setName(name:String):void {
	 	 this.name = name;
	 }
}
class Job {
	 private var name:String;                       Make it compile
	 private var steps:List[Step];
	 private var args:Map[String, Object];      •Public is default
	
	 getArgs():Map[String, Object] {
                                             •Variables are
	 	 return args;                              declared with var
	 }
	 setArgs(args:Map[String, Object]):void {   •Types after identifier
                                             •Generics with []
	 	 this.args = args;
	 }
   getSteps():List[Step] {
	 	 return steps;                            •Functions declared
	 }
	 setSteps(steps:List[Step]):void {
                                              with def
	 	 this.steps = steps;
	 }
                                             •= {...}
	 getName():String {
	 	 return name;
                                             •void ≈ Unit
	 }                                          •initialize var
	 setName(name:String):void {
	 	 this.name = name;
	 }
}
class Job {
	 private var name:String;                           Make it compile
	 private var steps:List[Step];
	 private var args:Map[String, Object];          •Public is default
	
	 def getArgs():Map[String, Object] {
                                                 •Variables are
	 	 return args;                                  declared with var
	 }
	 def setArgs(args:Map[String, Object]):void {   •Types after identifier
                                                 •Generics with []
	 	 this.args = args;
	 }
   def getSteps():List[Step] {
	 	 return steps;                                •Functions declared
	 }
	 def setSteps(steps:List[Step]):void {
                                                  with def
	 	 this.steps = steps;
	 }
                                                 •= {...}
	 def getName():String {
	 	 return name;
                                                 •void ≈ Unit
	 }                                              •initialize var
	 def setName(name:String):void {
	 	 this.name = name;
	 }
}
class Job {
	 private var name:String;                           Make it compile
	 private var steps:List[Step];
	 private var args:Map[String, Object];          •Public is default
	
	 def getArgs():Map[String, Object] {
                                                 •Variables are
	 	 return args;                                  declared with var
	 }
	 def setArgs(args:Map[String, Object]):void {   •Types after identifier
                                                 •Generics with []
	 	 this.args = args;
	 }
   def getSteps():List[Step] {
	 	 return steps;                                •Functions declared
	 }
	 def setSteps(steps:List[Step]):void {
                                                  with def
	 	 this.steps = steps;
	 }
                                                 •= {...}
	 def getName():String {
	 	 return name;
                                                 •void ≈ Unit
	 }                                              •initialize var
	 def setName(name:String):void {
	 	 this.name = name;
	 }
}
class Job {
	 private var name:String;                           Make it compile
	 private var steps:List[Step];
	 private var args:Map[String, Object];          •Public is default
	
	 def getArgs():Map[String, Object] {
                                                 •Variables are
	 	 return args;                                  declared with var
	 }
	 def setArgs(args:Map[String, Object]):void {   •Types after identifier
                                                 •Generics with []
	 	 this.args = args;
	 }
   def getSteps():List[Step] {
	 	 return steps;                                •Functions declared
	 }
	 def setSteps(steps:List[Step]):void {
                                                  with def
	 	 this.steps = steps;
	 }
                                                 •= {...}
	 def getName():String {
	 	 return name;
                                                 •void ≈ Unit
	 }                                              •initialize var
	 def setName(name:String):void {
	 	 this.name = name;
	 }
}
class Job {
	 private var name:String;                           Make it compile
	 private var steps:List[Step];
	 private var args:Map[String, Object];          •Public is default
	
	 def getArgs():Map[String, Object] {
                                                 •Variables are
	 	 return args;                                  declared with var
	 }
	 def setArgs(args:Map[String, Object]):void {   •Types after identifier
                                                 •Generics with []
	 	 this.args = args;
	 }
   def getSteps():List[Step] {
	 	 return steps;                                •Functions declared
	 }
	 def setSteps(steps:List[Step]):void {
                                                  with def
	 	 this.steps = steps;
	 }
                                                 •= {...}
	 def getName():String {
	 	 return name;
                                                 •void ≈ Unit
	 }                                              •initialize var
	 def setName(name:String):void {
	 	 this.name = name;
	 }
}
class Job {
	 private var name:String;                             Make it compile
	 private var steps:List[Step];
	 private var args:Map[String, Object];            •Public is default
	
	 def getArgs():Map[String, Object] = {
                                                   •Variables are
	 	 return args;                                    declared with var
	 }
	 def setArgs(args:Map[String, Object]):void = {   •Types after identifier
                                                   •Generics with []
	 	 this.args = args;
	 }
   def getSteps():List[Step] = {
	 	 return steps;                                  •Functions declared
	 }
	 def setSteps(steps:List[Step]):void = {
                                                    with def
	 	 this.steps = steps;
	 }
                                                   •= {...}
	 def getName():String = {
	 	 return name;
                                                   •void ≈ Unit
	 }                                                •initialize var
	 def setName(name:String):void = {
	 	 this.name = name;
	 }
}
class Job {
	 private var name:String;                             Make it compile
	 private var steps:List[Step];
	 private var args:Map[String, Object];            •Public is default
	
	 def getArgs():Map[String, Object] = {
                                                   •Variables are
	 	 return args;                                    declared with var
	 }
	 def setArgs(args:Map[String, Object]):void = {   •Types after identifier
                                                   •Generics with []
	 	 this.args = args;
	 }
   def getSteps():List[Step] = {
	 	 return steps;                                  •Functions declared
	 }
	 def setSteps(steps:List[Step]):void = {
                                                    with def
	 	 this.steps = steps;
	 }
                                                   •= {...}
	 def getName():String = {
	 	 return name;
                                                   •void ≈ Unit
	 }                                                •initialize var
	 def setName(name:String):void = {
	 	 this.name = name;
	 }
}
class Job {
	 private var name:String;                             Make it compile
	 private var steps:List[Step];
	 private var args:Map[String, Object];            •Public is default
	
	 def getArgs():Map[String, Object] = {
                                                   •Variables are
	 	 return args;                                    declared with var
	 }
	 def setArgs(args:Map[String, Object]):void = {   •Types after identifier
                                                   •Generics with []
	 	 this.args = args;
	 }
   def getSteps():List[Step] = {
	 	 return steps;                                  •Functions declared
	 }
	 def setSteps(steps:List[Step]):void = {
                                                    with def
	 	 this.steps = steps;
	 }
                                                   •= {...}
	 def getName():String = {
	 	 return name;
                                                   •void ≈ Unit
	 }                                                •initialize var
	 def setName(name:String):void = {
	 	 this.name = name;
	 }
}
class Job {
	 private var name:String;                             Make it compile
	 private var steps:List[Step];
	 private var args:Map[String, Object];            •Public is default
	
	 def getArgs():Map[String, Object] = {
                                                   •Variables are
	 	 return args;                                    declared with var
	 }
	 def setArgs(args:Map[String, Object]):void = {   •Types after identifier
                                                   •Generics with []
	 	 this.args = args;
	 }
   def getSteps():List[Step] = {
	 	 return steps;                                  •Functions declared
	 }
	 def setSteps(steps:List[Step]):void = {
                                                    with def
	 	 this.steps = steps;
	 }
                                                   •= {...}
	 def getName():String = {
	 	 return name;
                                                   •void ≈ Unit
	 }                                                •initialize var
	 def setName(name:String):void = {
	 	 this.name = name;
	 }
}
class Job {
	 private var name:String;                             Make it compile
	 private var steps:List[Step];
	 private var args:Map[String, Object];            •Public is default
	
	 def getArgs():Map[String, Object] = {
                                                   •Variables are
	 	 return args;                                    declared with var
	 }
	 def setArgs(args:Map[String, Object]):Unit = {   •Types after identifier
                                                   •Generics with []
	 	 this.args = args;
	 }
   def getSteps():List[Step] = {
	 	 return steps;                                  •Functions declared
	 }
	 def setSteps(steps:List[Step]):Unit = {
                                                    with def
	 	 this.steps = steps;
	 }
                                                   •= {...}
	 def getName():String = {
	 	 return name;
                                                   •void ≈ Unit
	 }                                                •initialize var
	 def setName(name:String):Unit = {
	 	 this.name = name;
	 }
}
class Job {
	 private var name:String;                             Make it compile
	 private var steps:List[Step];
	 private var args:Map[String, Object];            •Public is default
	
	 def getArgs():Map[String, Object] = {
                                                   •Variables are
	 	 return args;                                    declared with var
	 }
	 def setArgs(args:Map[String, Object]):Unit = {   •Types after identifier
                                                   •Generics with []
	 	 this.args = args;
	 }
   def getSteps():List[Step] = {
	 	 return steps;                                  •Functions declared
	 }
	 def setSteps(steps:List[Step]):Unit = {
                                                    with def
	 	 this.steps = steps;
	 }
                                                   •= {...}
	 def getName():String = {
	 	 return name;
                                                   •void ≈ Unit
	 }                                                •initialize var
	 def setName(name:String):Unit = {
	 	 this.name = name;
	 }
}
class Job {
	 private var name:String;                             Make it compile
	 private var steps:List[Step];
	 private var args:Map[String, Object];            •Public is default
	
	 def getArgs():Map[String, Object] = {
                                                   •Variables are
	 	 return args;                                    declared with var
	 }
	 def setArgs(args:Map[String, Object]):Unit = {   •Types after identifier
                                                   •Generics with []
	 	 this.args = args;
	 }
   def getSteps():List[Step] = {
	 	 return steps;                                  •Functions declared
	 }
	 def setSteps(steps:List[Step]):Unit = {
                                                    with def
	 	 this.steps = steps;
	 }
                                                   •= {...}
	 def getName():String = {
	 	 return name;
                                                   •void ≈ Unit
	 }                                                •initialize var
	 def setName(name:String):Unit = {
	 	 this.name = name;
	 }
}
class Job {
	 private var name:String;                             Make it compile
	 private var steps:List[Step];
	 private var args:Map[String, Object];            •Public is default
	
	 def getArgs():Map[String, Object] = {
                                                   •Variables are
	 	 return args;                                    declared with var
	 }
	 def setArgs(args:Map[String, Object]):Unit = {   •Types after identifier
                                                   •Generics with []
	 	 this.args = args;
	 }
   def getSteps():List[Step] = {
	 	 return steps;                                  •Functions declared
	 }
	 def setSteps(steps:List[Step]):Unit = {
                                                    with def
	 	 this.steps = steps;
	 }
                                                   •= {...}
	 def getName():String = {
	 	 return name;
                                                   •void ≈ Unit
	 }                                                •initialize var
	 def setName(name:String):Unit = {
	 	 this.name = name;
	 }
}
class Job {
	 private var name:String = null;                      Make it compile
	 private var steps:List[Step] = null;
	 private var args:Map[String, Object] = null;     •Public is default
	
	 def getArgs():Map[String, Object] = {
                                                   •Variables are
	 	 return args;                                    declared with var
	 }
	 def setArgs(args:Map[String, Object]):Unit = {   •Types after identifier
                                                   •Generics with []
	 	 this.args = args;
	 }
   def getSteps():List[Step] = {
	 	 return steps;                                  •Functions declared
	 }
	 def setSteps(steps:List[Step]):Unit = {
                                                    with def
	 	 this.steps = steps;
	 }
                                                   •= {...}
	 def getName():String = {
	 	 return name;
                                                   •void ≈ Unit
	 }                                                •initialize var
	 def setName(name:String):Unit = {
	 	 this.name = name;
	 }
}
class Job {
	 private var name:String = null;                      Make it compile
	 private var steps:List[Step] = null;
	 private var args:Map[String, Object] = null;     •Public is default
	
	 def getArgs():Map[String, Object] = {
                                                   •Variables are
	 	 return args;                                    declared with var
	 }
	 def setArgs(args:Map[String, Object]):Unit = {   •Types after identifier
                                                   •Generics with []
	 	 this.args = args;
	 }
   def getSteps():List[Step] = {
	 	 return steps;                                  •Functions declared
	 }
	 def setSteps(steps:List[Step]):Unit = {
                                                    with def
	 	 this.steps = steps;
	 }
                                                   •= {...}
	 def getName():String = {
	 	 return name;
                                                   •void ≈ Unit
	 }                                                •initialize var
	 def setName(name:String):Unit = {
	 	 this.name = name;
	 }
}
class Job {
	 private var name:String = null;                      Make it compile
	 private var steps:List[Step] = null;
	 private var args:Map[String, Object] = null;     •Public is default
	
	 def getArgs():Map[String, Object] = {
                                                   •Variables are
	 	 return args;                                    declared with var
	 }
	 def setArgs(args:Map[String, Object]):Unit = {   •Types after identifier
                                                   •Generics with []
	 	 this.args = args;
	 }
   def getSteps():List[Step] = {
	 	 return steps;                                  •Functions declared
	 }
	 def setSteps(steps:List[Step]):Unit = {
                                                    with def
	 	 this.steps = steps;
	 }
                                                   •= {...}
	 def getName():String = {
	 	 return name;
                                                   •void ≈ Unit
	 }                                                •initialize var
	 def setName(name:String):Unit = {
	 	 this.name = name;
	 }
}
class Job {
	 private var name:String = null;                      Make it compile
	 private var steps:List[Step] = null;
	 private var args:Map[String, Object] = null;     •Public is default
	
	 def getArgs():Map[String, Object] = {
                                                   •Variables are
	 	 return args;                                    declared with var
	 }
	 def setArgs(args:Map[String, Object]):Unit = {   •Types after identifier
                                                   •Generics with []
	 	 this.args = args;
	 }
   def getSteps():List[Step] = {
	 	 return steps;                                  •Functions declared
	 }
	 def setSteps(steps:List[Step]):Unit = {
                                                    with def
	 	 this.steps = steps;
	 }
                                                   •= {...}
	 def getName():String = {
	 	 return name;
                                                   •void ≈ Unit
	 }                                                •initialize var
	 def setName(name:String):Unit = {
	 	 this.name = name;
	 }
}
class Job {
	 private var name:String = null;          Make it compile
	 private var steps:List[Step] = null;
                                       •Public is default
	 private var args:Map[String, Object] = null;
	
	 def getArgs():Map[String, Object] = {
                                       •Variables are
	 	 return args;                        declared with var
	 }
                                       •Types after identifier
	 def setArgs(args:Map[String, Object]):Unit = {

                                       •Generics with []
	 	 this.args = args;
	 }
                         IT COMPILES
   def getSteps():List[Step] = {
	 	 return steps;                      •Functions declared
	 }              BUT IT’S JAVA WITH SCALA SYNTAX
                                        with def
	 def setSteps(steps:List[Step]):Unit = {
	 	 this.steps = steps;
	 }
                                       •= {...}
	 def getName():String = {
	 	 return name;
                                       •void ≈ Unit
	 }                                    •initialize var
	 def setName(name:String):Unit = {
	 	 this.name = name;
	 }
}
class Job {
	 private var name:String = null;                    Remove redundancy
	 private var steps:List[Step] = null;
	 private var args:Map[String, Object] = null;     •The last statement is
	
	 def getArgs():Map[String, Object] = {
                                                    returned
	 	 return args;
	 }
                                                   •Types are inferred
	 def setArgs(args:Map[String, Object]):Unit = {   •No = implies Unit
                                                   •Single statement
	 	 this.args = args;
	 }
   def getSteps():List[Step] = {
	 	 return steps;                                   doesn’t need a block
	 }
	 def setSteps(steps:List[Step]):Unit = {
                                                   •New line implies ;
	 	 this.steps = steps;
	 }
	 def getName():String = {
	 	 return name;
	 }
	 def setName(name:String):Unit = {
	 	 this.name = name;
	 }
}
class Job {
	 private var name:String = null;                    Remove redundancy
	 private var steps:List[Step] = null;
	 private var args:Map[String, Object] = null;     •The last statement is
	
	 def getArgs():Map[String, Object] = {
                                                    returned
	 	 return args;
	 }
                                                   •Types are inferred
	 def setArgs(args:Map[String, Object]):Unit = {   •No = implies Unit
                                                   •Single statement
	 	 this.args = args;
	 }
   def getSteps():List[Step] = {
	 	 return steps;                                   doesn’t need a block
	 }
	 def setSteps(steps:List[Step]):Unit = {
                                                   •New line implies ;
	 	 this.steps = steps;
	 }
	 def getName():String = {
	 	 return name;
	 }
	 def setName(name:String):Unit = {
	 	 this.name = name;
	 }
}
class Job {
	 private var name:String = null;                    Remove redundancy
	 private var steps:List[Step] = null;
	 private var args:Map[String, Object] = null;     •The last statement is
	
	 def getArgs():Map[String, Object] = {
                                                    returned
	 	 return args;
	 }
                                                   •Types are inferred
	 def setArgs(args:Map[String, Object]):Unit = {   •No = implies Unit
                                                   •Single statement
	 	 this.args = args;
	 }
   def getSteps():List[Step] = {
	 	 return steps;                                   doesn’t need a block
	 }
	 def setSteps(steps:List[Step]):Unit = {
                                                   •New line implies ;
	 	 this.steps = steps;
	 }
	 def getName():String = {
	 	 return name;
	 }
	 def setName(name:String):Unit = {
	 	 this.name = name;
	 }
}
class Job {
	 private var name:String = null;                    Remove redundancy
	 private var steps:List[Step] = null;
	 private var args:Map[String, Object] = null;     •The last statement is
	
	 def getArgs():Map[String, Object] = {
                                                    returned
	 	 args;
	 }
                                                   •Types are inferred
	 def setArgs(args:Map[String, Object]):Unit = {   •No = implies Unit
                                                   •Single statement
	 	 this.args = args;
	 }
   def getSteps():List[Step] = {
	 	 steps;                                          doesn’t need a block
	 }
	 def setSteps(steps:List[Step]):Unit = {
                                                   •New line implies ;
	 	 this.steps = steps;
	 }
	 def getName():String = {
	 	 name;
	 }
	 def setName(name:String):Unit = {
	 	 this.name = name;
	 }
}
class Job {
	 private var name:String = null;                    Remove redundancy
	 private var steps:List[Step] = null;
	 private var args:Map[String, Object] = null;     •The last statement is
	
	 def getArgs():Map[String, Object] = {
                                                    returned
	 	 args;
	 }
                                                   •Types are inferred
	 def setArgs(args:Map[String, Object]):Unit = {   •No = implies Unit
                                                   •Single statement
	 	 this.args = args;
	 }
   def getSteps():List[Step] = {
	 	 steps;                                          doesn’t need a block
	 }
	 def setSteps(steps:List[Step]):Unit = {
                                                   •New line implies ;
	 	 this.steps = steps;
	 }
	 def getName():String = {
	 	 name;
	 }
	 def setName(name:String):Unit = {
	 	 this.name = name;
	 }
}
class Job {
	 private var name:String = null;                    Remove redundancy
	 private var steps:List[Step] = null;
	 private var args:Map[String, Object] = null;     •The last statement is
	
	 def getArgs() = {
                                                    returned
	 	 args;
	 }
                                                   •Types are inferred
	 def setArgs(args:Map[String, Object]):Unit = {   •No = implies Unit
                                                   •Single statement
	 	 this.args = args;
	 }
   def getSteps() = {
	 	 steps;                                          doesn’t need a block
	 }
	 def setSteps(steps:List[Step]):Unit = {
                                                   •New line implies ;
	 	 this.steps = steps;
	 }
	 def getName() = {
	 	 name;
	 }
	 def setName(name:String):Unit = {
	 	 this.name = name;
	 }
}
class Job {
	 private var name:String = null;                    Remove redundancy
	 private var steps:List[Step] = null;
	 private var args:Map[String, Object] = null;     •The last statement is
	
	 def getArgs() = {
                                                    returned
	 	 args;
	 }
                                                   •Types are inferred
	 def setArgs(args:Map[String, Object]):Unit = {   •No = implies Unit
                                                   •Single statement
	 	 this.args = args;
	 }
   def getSteps() = {
	 	 steps;                                          doesn’t need a block
	 }
	 def setSteps(steps:List[Step]):Unit = {
                                                   •New line implies ;
	 	 this.steps = steps;
	 }
	 def getName() = {
	 	 name;
	 }
	 def setName(name:String):Unit = {
	 	 this.name = name;
	 }
}
class Job {
	 private var name:String = null;                  Remove redundancy
	 private var steps:List[Step] = null;
	 private var args:Map[String, Object] = null;   •The last statement is
	
	 def getArgs() = {
                                                  returned
	 	 args;
	 }
                                                 •Types are inferred
	 def setArgs(args:Map[String, Object]) {        •No = implies Unit
                                                 •Single statement
	 	 this.args = args;
	 }
   def getSteps() = {
	 	 steps;                                        doesn’t need a block
	 }
	 def setSteps(steps:List[Step]) {
                                                 •New line implies ;
	 	 this.steps = steps;
	 }
	 def getName() = {
	 	 name;
	 }
	 def setName(name:String) {
	 	 this.name = name;
	 }
}
class Job {
	 private var name:String = null;                  Remove redundancy
	 private var steps:List[Step] = null;
	 private var args:Map[String, Object] = null;   •The last statement is
	
	 def getArgs() = {
                                                  returned
	 	 args;
	 }
                                                 •Types are inferred
	 def setArgs(args:Map[String, Object]) {        •No = implies Unit
                                                 •Single statement
	 	 this.args = args;
	 }
   def getSteps() = {
	 	 steps;                                        doesn’t need a block
	 }
	 def setSteps(steps:List[Step]) {
                                                 •New line implies ;
	 	 this.steps = steps;
	 }
	 def getName() = {
	 	 name;
	 }
	 def setName(name:String) {
	 	 this.name = name;
	 }
}
class Job {
	 private var name:String = null;                  Remove redundancy
	 private var steps:List[Step] = null;
	 private var args:Map[String, Object] = null;   •The last statement is
	
	 def getArgs() = args;
                                                  returned
                                                 •Types are inferred
	   def setArgs(args:Map[String, Object]) {      •No = implies Unit
                                                 •Single statement
	   	 this.args = args;
	   }
	   def getSteps() = steps;
                                                  doesn’t need a block
	   def setSteps(steps:List[Step]) {
                                                 •New line implies ;
	   	 this.steps = steps;
	   }
	   def getName() = name;



	   def setName(name:String) {
	   	 this.name = name;
	   }
}
class Job {
	 private var name:String = null;                  Remove redundancy
	 private var steps:List[Step] = null;
	 private var args:Map[String, Object] = null;   •The last statement is
	
	 def getArgs() = args;
                                                  returned
                                                 •Types are inferred
	   def setArgs(args:Map[String, Object]) {      •No = implies Unit
                                                 •Single statement
	   	 this.args = args;
	   }
	   def getSteps() = steps;
                                                  doesn’t need a block
	   def setSteps(steps:List[Step]) {
                                                 •New line implies ;
	   	 this.steps = steps;
	   }
	   def getName() = name;



	   def setName(name:String) {
	   	 this.name = name;
	   }
}
class Job {
	 private var name:String = null                  Remove redundancy
	 private var steps:List[Step] = null
	 private var args:Map[String, Object] = null   •The last statement is
	
	 def getArgs() = args
                                                 returned
                                                •Types are inferred
	   def setArgs(args:Map[String, Object]) {     •No = implies Unit
                                                •Single statement
	   	 this.args = args
	   }
	   def getSteps() = steps
                                                 doesn’t need a block
	   def setSteps(steps:List[Step]) {
                                                •New line implies ;
	   	 this.steps = steps
	   }
	   def getName() = name



	   def setName(name:String) {
	   	 this.name = name
	   }
}
class Job {
	 private var name:String = null                  Remove redundancy
	 private var steps:List[Step] = null
	 private var args:Map[String, Object] = null   •The last statement is
	
	 def getArgs() = args
                                                 returned
                                                •Types are inferred
	   def setArgs(args:Map[String, Object]) {     •No = implies Unit
                                                •Single statement
	   	 this.args = args
	   }
	   def getSteps() = steps
                                                 doesn’t need a block
	   def setSteps(steps:List[Step]) {
                                                •New line implies ;
	   	 this.steps = steps
	   }
	   def getName() = name



	   def setName(name:String) {
	   	 this.name = name
	   }
}
class Job {
	 private var name:String = null                      Redundancy
	 private var steps:List[Step] = null
	 private var args:Map[String, Object] = null   •The last statement is
	
	 def getArgs() = args
                                                 returned
                                                •Types are inferred
	   def setArgs(args:Map[String, Object]) {     •No = implies Unit
                                                •Single statement
	   	 this.args = args
	   }
	   def getSteps() = steps
                                                 doesn’t need a block
	   def setSteps(steps:List[Step]) {
                                                •New line implies ;
	   	 this.steps = steps
	   }
	   def getName() = name



	   def setName(name:String) {
	   	 this.name = name
	   }
}
class Job {
	 private var name:String = null
	 private var steps:List[Step] = null
	 private var args:Map[String, Object] = null
	
	 def getArgs() = args



	   def setArgs(args:Map[String, Object]) {
	   	 this.args = args
	   }
	   def getSteps() = steps                      There is an even
                                                 shorter form!
	   def setSteps(steps:List[Step]) {
	   	 this.steps = steps
	   }
	   def getName() = name



	   def setName(name:String) {
	   	 this.name = name
	   }
}
class Job {                                     import scala.reflect._
	 private var name:String = null                class Job {
	 private var steps:List[Step] = null           	 @BeanProperty
	 private var args:Map[String, Object] = null   	 var name:String = null
	                                               	 @BeanProperty
	 def getArgs() = args                          	 var steps:List[Step] = null
                                                	 @BeanProperty
                                                	 var args:Map[String, Object] = null
	   def setArgs(args:Map[String, Object]) {     }
	   	 this.args = args
	   }
	   def getSteps() = steps



	   def setSteps(steps:List[Step]) {
	   	 this.steps = steps
	   }
	   def getName() = name



	   def setName(name:String) {
	   	 this.name = name
	   }
}
public class Job {                           import scala.reflect._
	 private String name;                       class Job {
	 private List<Step> steps;                  	 @BeanProperty
	 private Map<String, Object> args;          	 var name:String = null
                                             	 @BeanProperty
	 public Map<String, Object> getArgs() {     	 var steps:List[Step] = null
	 	 return args;                             	 @BeanProperty
	 }                                          	 var args:Map[String, Object] = null
	 public void setArgs(Map<String, Object>    }
args) {
	 	 this.args = args;
	 }
	 public List<Step> getSteps() {
	 	 return steps;
	 }
	 public void setSteps(List<Step> steps) {
	 	 this.steps = steps;
	 }
	 public String getName() {
	 	 return name;
	 }
	 public void setName(String name) {
	 	 this.name = name;
	 }
}
public class Job {                           import scala.reflect._
	 private String name;                       class Job {
	 private List<Step> steps;                  	 @BeanProperty
	 private Map<String, Object> args;          	 var name:String = null
                                             	 @BeanProperty
	 public Map<String, Object> getArgs() {     	 var steps:List[Step] = null
	 	 return args;                             	 @BeanProperty
	 }                                          	 var args:Map[String, Object] = null
	 public void setArgs(Map<String, Object>    }
args) {
	 	 this.args = args;



               SCALA                          SMALL
	 }
	 public List<Step> getSteps() {
	 	 return steps;
	 }
	 public void setSteps(List<Step> steps) {
	 	 this.steps = steps;
	 }
	 public String getName() {
	 	 return name;
	 }
	 public void setName(String name) {
	 	 this.name = name;
	 }
}
public class Job {                            import scala.reflect._
	 private String name;                        class Job {
	 private List<Step> steps;                   	 @BeanProperty
	 private Map<String, Object> args;           	 var name:String = null
                                              	 @BeanProperty
	 public Map<String, Object> getArgs() {      	 var steps:List[Step] = null
	 	 return args;                              	 @BeanProperty
	 }                                           	 var args:Map[String, Object] = null
	 public void setArgs(Map<String, Object>     }



                   More compact
args) {
	 	 this.args = args;
	 }
	 public List<Step> getSteps() {
	 	 return steps;
	 }
                              But still a Java mindset
	 public void setSteps(List<Step> steps) {
	 	 this.steps = steps;
	 }
	 public String getName() {
	 	 return name;
	 }
	 public void setName(String name) {
	 	 this.name = name;
	 }
}
import scala.reflect._
class Job {                               [Make it immutable]
	 @BeanProperty
	 var name:String = null                •Add a constructor
	 @BeanProperty
	 var steps:List[Step] = null
                                        •Make fields immutable
	 @BeanProperty
	 var args:Map[String, Object] = null
                                        •Use default
                                         arguments
                                        •Create by name
}
import scala.reflect._
class Job {                               [Make it immutable]
	 @BeanProperty
	 var name:String = null                •Add a constructor
	 @BeanProperty
	 var steps:List[Step] = null
                                        •Make fields immutable
	 @BeanProperty
	 var args:Map[String, Object] = null
                                        •Use default
                                         arguments
                                        •Create by name
}
import scala.reflect._
class Job (                        [Make it immutable]
	 @BeanProperty
	 var name:String,               •Add a constructor
	 @BeanProperty
	 var steps:List[Step],
                                 •Make fields immutable
	 @BeanProperty
	 var args:Map[String, Object]
                                 •Use default
                                  arguments
                                 •Create by name
)
{
}
import scala.reflect._
class Job (                        [Make it immutable]
	 @BeanProperty
	 var name:String,               •Add a constructor
	 @BeanProperty
	 var steps:List[Step],
                                 •Make fields immutable
	 @BeanProperty
	 var args:Map[String, Object]
                                 •Use default
                                  arguments
                                 •Create by name
)
{
}
import scala.reflect._
class Job (                        [Make it immutable]
	 @BeanProperty
	 val name:String,               •Add a constructor
	 @BeanProperty
	 val steps:List[Step],
                                 •Make fields immutable
	 @BeanProperty
	 val args:Map[String, Object]
                                 •Use default
                                  arguments
                                 •Create by name
)
{
}
import scala.reflect._
class Job (                        [Make it immutable]
	 @BeanProperty
	 val name:String,               •Add a constructor
	 @BeanProperty
	 val steps:List[Step],
                                 •Make fields immutable
	 @BeanProperty
	 val args:Map[String, Object]
                                 •Use default
                                  arguments
                                 •Create by name
)
{
}
import scala.reflect._
class Job (                             [Make it immutable]
	 @BeanProperty
	 val name:String = “no name”,        •Add a constructor
	 @BeanProperty
	 val steps:List[Step] = emptyList,
                                      •Make fields immutable
	 @BeanProperty
	 val args:Map[String, Object] =
                                      •Use default
	 	 	 	 	 	 	            emptyMap      arguments
                                      •Create by name
)
{
}
import scala.reflect._
class Job (                             [Make it immutable]
	 @BeanProperty
	 val name:String = “no name”,        •Add a constructor
	 @BeanProperty
	 val steps:List[Step] = emptyList,
                                      •Make fields immutable
	 @BeanProperty
	 val args:Map[String, Object] =
                                      •Use default
	 	 	 	 	 	 	            emptyMap      arguments
                                      •Create by name
)
{
}
import scala.reflect._
class Job (                             [Make it immutable]
	 @BeanProperty
	 val name:String = “no name”,        •Add a constructor
	 @BeanProperty
	 val steps:List[Step] = emptyList,
                                      •Make fields immutable
	 @BeanProperty
	 val args:Map[String, Object] =
                                      •Use default
	 	 	 	 	 	 	            emptyMap      arguments
                                      •Create by name
)
{
}

new Job (
	 name = “an empty job”
)
import scala.reflect._
class Job (                             [Make it immutable]
	 @BeanProperty
	 val name:String = “no name”,        •Add a constructor
	 @BeanProperty
	 val steps:List[Step] = emptyList,
                                      •Make fields immutable
	 @BeanProperty
	 val args:Map[String, Object] =
                                      •Use default
	 	 	 	 	 	 	            emptyMap      arguments
                                      •Create by name
)
{
}

new Job (
	 name = “an empty job”
)
WHY SCALA?
WHY NOT JAVA?
JAVA HAS EVOLVED
1.1
      Inn
          er
               cla
                  sse
                     s




1.2
        str
      co ictfp
        lle
            cti key
               on wo
                   lib rd,
                       rar re



1.4
       ass                y fle
           er                         cti
              tk                          on
                  ey
                     wo                     ,
        En               rd
1.5   an ums
        no , g
            tat en
                ion eri
                    s, s cs,
                        tat
1.7


       Ho                   ic
                               im
                                                JAVA HAS EVOLVED




           or
               ay                 po
                  !P                  r ts
                     ro
                        jec
                            tC
                                oin
                                    !
1.1
                                                          Inn
                                                              er
                                                                   cla
                                                                      sse
                                                                         s




                                                    1.2
                                                            str
                                                          co ictfp
                                                            lle
                                                                cti key
                                                                   on wo
                                                                       lib rd,
                                                                           rar re



                                                    1.4
                                                           ass                y fle
                                                               er                         cti
                                                                  tk                          on
                                                                      ey
                                                                         wo                     ,
                                                            En               rd
                                                    1.5   an ums
                                                            no , g
                                                                tat en
                                                                    ion eri
                                                                        s, s cs,
                                                                            tat
                                                    1.7


                                                           Ho                   ic
                                                                                   im
                                                                                                    JAVA HAS EVOLVED




                                                               or
                                                                   ay                 po
                                                                      !P
Good concepts have to be twisted to fit into Java



                                                                         ro               r ts
                                                                            jec
                                                                                tC
                                                                                    oin
                                                                                        !
Scala For Java Programmers
Java
1996 -2006
Java
             Coooooobooool
1996 -2006
Java
1996 -2006
WHY SCALA AGAIN?

•Byte   code compatible with Java
•Designed    for extendability
•A   higher level of abstraction
"If I'd asked my customers what they wanted,
they'd have said a faster horse." - Henry Ford
Scala For Java Programmers
PROJECT LAYOUT


   Java             Scala       Java
Application        Module      Module
PROJECT LAYOUT

                  JobControl.scala
   Java                Scala          Java
Application           Module         Module
Exploit Scala
public class JobControl {
	 private JobFactory jf;                    Move a “logic” class
	
	 public JobControl(JobFactory jf) {       from Java to Scala so
	 	 this.jf = jf;
	 }
                                           that we can use Scala
	                                            for more than just
	 public void startJob(String name) {
	 	 Job job = jf.create(name);                     beans
	 	 if (job != null) {
	 	 	 Map<String, Object> context =
	 	 	 	 new HashMap<String, Object>();
	 	 	 for (Step step : job.getSteps()) {
	 	 	 	 step.getCommand().run(context);
	 	 	 }
	 	 }
	 }
}
Exploit Scala
class JobControl(jf:JobFactory) {          Same steps as before




	   def startJob(name:String) = {
	   	 val job = jf.create(name)
	   	 if (job != null) {
	   	 	 val context =
	   	 	 	 new HashMap[String, Object]()
	   	 	 for (step <- job.getSteps()) {
	   	 	 	 step.getCommand().run(context)
	   	 	 }
	   	 }
	   }
}
Exploit Scala
class JobControl(jf:JobFactory) {          Same steps as before

                                           Observe the for syntax


	   def startJob(name:String) = {
	   	 val job = jf.create(name)
	   	 if (job != null) {
	   	 	 val context =
	   	 	 	 new HashMap[String, Object]()
	   	 	 for (step <- job.getSteps()) {
	   	 	 	 step.getCommand().run(context)
	   	 	 }
	   	 }
	   }
}
Exploit Scala
class JobControl(jf:JobFactory) {          Same steps as before

                                           Observe the for syntax


	   def startJob(name:String) = {
                                             Does not compile,
	   	 val job = jf.create(name)             needs the result of
	   	 if (job != null) {
	   	 	 val context =                      getSteps to implement
	   	 	 	 new HashMap[String, Object]()      a foreach-method
	   	 	 for (step <- job.getSteps()) {
	   	 	 	 step.getCommand().run(context)
	   	 	 }
	   	 }
	   }
}
Exploit Scala
class JobControl(jf:JobFactory) {          Same steps as before

                                           Observe the for syntax


	   def startJob(name:String) = {
                                             Does not compile,
	   	 val job = jf.create(name)             needs the result of
	   	 if (job != null) {
	   	 	 val context =                      getSteps to implement
	   	 	 	 new HashMap[String, Object]()      a foreach-method
	   	 	 for (step <- job.getSteps()) {
	   	 	 	 step.getCommand().run(context)
	   	 	 }
	   	 }                                        Tip: Google for
	
}
    }
                                             “structural typing”
import scala.collection.JavaConversions._
                                             Exploit Scala
class JobControl(jf:JobFactory) {           Scala 2.8 to the
                                                 rescue:



	   def startJob(name:String) = {
	   	 val job = jf.create(name)
	   	 if (job != null) {
	   	 	 val context =
	   	 	 	 new HashMap[String, Object]()
	   	 	 for (step <- job.getSteps()) {
	   	 	 	 step.getCommand().run(context)
	   	 	 }
	   	 }
	   }
}
import scala.collection.JavaConversions._
                                             Exploit Scala
class JobControl(jf:JobFactory) {           Scala 2.8 to the
                                                 rescue:
                                              Implicit java
                                              conversions!
	   def startJob(name:String) = {
	   	 val job = jf.create(name)
	   	 if (job != null) {
	   	 	 val context =
	   	 	 	 new HashMap[String, Object]()
	   	 	 for (step <- job.getSteps()) {
	   	 	 	 step.getCommand().run(context)
	   	 	 }
	   	 }
	   }
}
import scala.collection.JavaConversions._
                                             Exploit Scala
class JobControl(jf:JobFactory) {           Scala 2.8 to the
                                                 rescue:
                                              Implicit java
                                              conversions!
	   def startJob(name:String) = {
	   	 val job = jf.create(name)
	   	 if (job != null) {
	   	 	 val context =
	   	 	 	 new HashMap[String, Object]()
	   	 	 for (step <- job.getSteps()) {
	   	 	 	 step.getCommand().run(context)
	   	 	 }
	   	 }
	   }
}
import scala.collection.JavaConversions._
                                             Exploit Scala
class JobControl(jf:JobFactory) {           Scala 2.8 to the
                                                 rescue:
                                              Implicit java
                                              conversions!
	   def startJob(name:String) = {


               SCALA ☠ NULL
	   	 val job = jf.create(name)
	   	 if (job != null) {
	   	 	 val context =
	   	 	 	 new HashMap[String, Object]()
	   	 	 for (step <- job.getSteps()) {
	   	 	 	 step.getCommand().run(context)
	   	 	 }
	   	 }
	   }
}
import scala.collection.JavaConversions._
                                             Exploit Scala
class JobControl(jf:JobFactory) {           Scala 2.8 to the
                                                 rescue:
                                              Implicit java
                                              conversions!
	   def startJob(name:String) = {
	
	
	
         SCALA
    	 val job = jf.create(name)
    	 if (job != null) {
    	 	 val context =
                                       OPTIONS
	   	 	 	 new HashMap[String, Object]()
	   	 	 for (step <- job.getSteps()) {
	   	 	 	 step.getCommand().run(context)
	   	 	 }
	   	 }
	   }
}
import scala.collection.JavaConversions._
                                             Exploit Scala
class JobControl(jf:JobFactory) {           Scala 2.8 to the
                                                 rescue:
                                              Implicit java
                                              conversions!
	   def startJob(name:String) = {
	   	 val job = jf.create(name)
	   	 if (job != null) {
	   	 	 val context =
	   	 	 	 new HashMap[String, Object]()
	   	 	 for (step <- job.getSteps()) {
	   	 	 	 step.getCommand().run(context)
	   	 	 }
	   	 }
	   }
}
trait JobFactory {
	 def create(name:String):Job      Exploit Scala
                                Scala’s equivalent of
                                     interfaces:

                                       Traits


}
trait JobFactory {
	 def create(name:String):Job              Exploit Scala
	 def apply(name:String):Option[Job]   Create an alternative
                                       method that optionally
                                           returns a Job

                                        As we will see, the
                                        name “apply” has a
}
                                        special meaning in
                                               Scala
trait JobFactory {
	 def create(name:String):Job                   Exploit Scala
	 def apply(name:String):Option[Job] = {       Traits can have
	     val job = create(name)
	     if (job == null) {                      implementations
	 	      None
	     }
	     else {                               Mix ins: “Compiler copy
	 	      Some(job)
	     }                                          + paste :)”
	 }
}
trait JobFactory {
	 def create(name:String):Job                   Exploit Scala
	 def apply(name:String):Option[Job] = {       Traits can have
	     val job = create(name)
	     if (job == null) {                      implementations
	 	      None
	     }
	     else {                               Mix ins: “Compiler copy
	 	      Some(job)
	     }                                          + paste :)”
	 }
}

                                             Everything has a
                                              value in Scala!
trait JobFactory {
	 def create(name:String):Job                  Exploit Scala
	 def apply(name:String):Option[Job] = {   Java will only see the
	     val job = create(name)
	     if (job == null) {                   interface so we need
	 	
	     }
         None
                                                an adapter.
	     else {
	 	      Some(job)
	     }                                    An abstract base-class?
	 }
}

abstract class AbstractJobFactory
         extends Object with JobFactory
trait JobFactory {
	 def create(name:String):Job                  Exploit Scala
	 def apply(name:String):Option[Job] = {   Pattern-matching is
	     val job = create(name)
	 	 job match {                            more compact, more
	 	      case null => None
                                           “scala” and can give
                                            you more compiler
	   	       case job => Some(job)
	       }                                        support.
	   }
}
                                           NOT THE SAME AS
abstract class AbstractJobFactory
         extends Object with JobFactory
                                           SWITCH CASE IN
                                                JAVA!!!
import scala.collection.JavaConversions._
                                                    Exploit Scala
class JobControl(jf:JobFactory) {                 Time to use our
	 def startJob(name:String) = {
	 	 val job = jf.create(name)                   “improved” factory

	   	   if   (job != null) {
	   	   	    val context =
	   	   	    	 new HashMap[String, Object]()
	   	   	    for (step <- job.getSteps()) {
	   	   	    	 step.getCommand().run(context)
	   	   	    }
	   	   }
	   }
}
import scala.collection.JavaConversions._
                                                    Exploit Scala
class JobControl(jf:JobFactory) {              The option “enforces”
	 def startJob(name:String) = {
	 	 val job = jf.apply(name).                   handling the None-
                   getOrElse(EMPTY_JOB)
                                             case. You can’t get the
                                                  value unless you
          val context =
          	 new HashMap[String, Object]()    provide what to return
          for (step <- job.getSteps()) {      if the option is empty
          	 step.getCommand().run(context)
          }                                            (None)
    	 }
}
import scala.collection.JavaConversions._
                                                    Exploit Scala
class JobControl(jf:JobFactory) {              The option “enforces”
	 def startJob(name:String) = {
	 	 val job = jf.apply(name).                   handling the None-
                   getOrElse(EMPTY_JOB)
                                             case. You can’t get the
                                                  value unless you
          val context =
          	 new HashMap[String, Object]()    provide what to return
          for (step <- job.getSteps()) {      if the option is empty
          	 step.getCommand().run(context)
          }                                            (None)
    	 }
}
import scala.collection.JavaConversions._
                                                Exploit Scala
class JobControl(jf:JobFactory) {            Told you the apply
	 def startJob(name:String) = {
	 	 val job = jf(name).                      name was special!
                   getOrElse(EMPTY_JOB)



	    	    val context =
	    	    	 new HashMap[String, Object]()
	    	    for (step <- job.getSteps()) {
	    	    	 step.getCommand().run(context)
	    	    }

    	 }
}
import scala.collection.JavaConversions._
                                                 Exploit Scala
class JobControl(jf:JobFactory) {             We can also execute
	 def startJob(name:String) = {
      val job = jf(name).                     code if the option is
                   getOrElse(
	 	 	 {println(“hello”)
                                                     empty
         error("No job with name: "+name)})
	 	 val context =
         new HashMap[String, Object]()
	 	 for (step <- job.getSteps()) {
	 	 	 step.getCommand().run(context)
	 	 }

	   }
}
import scala.collection.JavaConversions._
                                                 Exploit Scala
class JobControl(jf:JobFactory) {             We can also execute
	 def startJob(name:String) = {
      val job = jf(name).                     code if the option is
                   getOrElse(
	 	 	 {println(“hello”)
                                                     empty
         error("No job with name: "+name)})
	 	 val context =
         new HashMap[String, Object]()


        SCALA
	 	 for (step <- job.getSteps()) {
                                   FUNCTIONS
	 	 	 step.getCommand().run(context)
	 	 }

	   }
}
SCALA   FUNCTIONS
SCALA   FUNCTIONS
SCALA   FUNCTIONS

AC             DC
SCALA   FUNCTIONS

           AC   DC
SCALA   FUNCTIONS

           AC   DC
SCALA   FUNCTIONS

          ( AC ) => DC
SCALA        FUNCTIONS
                     Type
val transformer: ( AC ) => DC
SCALA       FUNCTIONS

 (   AC ) => DC
SCALA       FUNCTIONS

 ( String ) => Option[Job]
SCALA         FUNCTIONS

   ( String ) => Option[Job]


Function[String, Option[Job]]
import scala.collection.JavaConversions._
                                                 Exploit Scala
class JobControl(jf:JobFactory) {             We can also execute
	 def startJob(name:String) = {
      val job = jf(name).                     code if the option is
                   getOrElse(
	 	 	 {println(“hello”)
                                                     empty
         error("No job with name: "+name)})
	 	 val context =
         new HashMap[String, Object]()


        SCALA
	 	 for (step <- job.getSteps()) {
                                   FUNCTIONS
	 	 	 step.getCommand().run(context)
	 	 }

	   }
}
import scala.collection.JavaConversions._
                                                 Exploit Scala
class JobControl(jf:JobFactory) {             We can also execute
	 def startJob(name:String) = {
      val job = jf(name).                     code if the option is
                   getOrElse(
	 	 	 {println(“hello”)
                                                     empty
         error("No job with name: "+name)})
	 	 val context =
         new HashMap[String, Object]()
	 	 for (step <- job.getSteps()) {
	 	 	 step.getCommand().run(context)
	 	 }

	   }
}
trait JobFactory {
	
                                                 Use functions
                                             Functions as Factories
	   def create(name:String):Job
	   def apply(name:String):Option[Job] = {
                                             Factories as Functions
	      create(name) match {
	   	     case null => None
	   	     case job => Some(job)
	      }
	   }
}

abstract class AbstractJobFactory
	 	 	 extends Object with JobFactory
trait JobFactory
	 extends	 Function[String, Option[Job]] {
                                                Use functions
	
	 def create(name:String):Job
	 def apply(name:String):Option[Job] = {
                                             Functions are objects
	     create(name) match {                   and can be extended
	 	      case null => None
	 	      case job => Some(job)
	     }                                      We already implement
	 }
}
                                                    apply

abstract class AbstractJobFactory
	 	 	 extends Object with JobFactory
import scala.collection.JavaConversions._
                                                Use functions
class JobControl(jf:JobFactory) {
	 def startJob(name:String) = {
	 	 val job = jf(name).                      We can now change
	 	 val context =
                   getOrElse(EMPTY_JOB)
                                            our dependencies from
	 	 	 new HashMap[String, Object]()              JobControl...
	 	 for (step <- job.getSteps()) {
	 	 	 step.getCommand().run(context)
	 	 }
  	 }
}
import scala.collection.JavaConversions._
                                                Use functions
class JobControl(jf:JobFactory) {
	 def startJob(name:String) = {
	 	 val job = jf(name).                      We can now change
	 	 val context =
                   getOrElse(EMPTY_JOB)
                                            our dependencies from
	 	 	 new HashMap[String, Object]()              JobControl...
	 	 for (step <- job.getSteps()) {
	 	 	 step.getCommand().run(context)
	 	 }
  	 }
}
import scala.collection.JavaConversions._
                                                  Use functions
class JobControl(jf:(String)=>Option[Job]) {
	 def startJob(name:String) = {
	 	 val job = jf(name).                          Let’s depend on a
	 	 val context =
                   getOrElse(EMPTY_JOB)
                                               function instead of a
	 	 	 new HashMap[String, Object]()                    factory
	 	 for (step <- job.getSteps()) {
	 	 	 step.getCommand().run(context)
	 	 }
  	 }
}
FUNCTIONS AS FACTORIES

def emptyJobFactory(name:String) = {
	 Some(new Job(name, emptyJavaList, emptyJavaMap))
}

new JobControl(emptyJobFactory)
PROJECT LAYOUT


   Java             Scala       Java
Application        Module      Module
PROJECT LAYOUT

 Main.java
   Java             Scala       Java
Application        Module      Module
STILL A FACTORY IN JAVA!
                                                 Defined in Java

public static void main(String[] args) {         Defined in Scala


         JobFactory factory = new JdbcJobFactory();

         JobControl control = new JobControl(factory);

         ...
}
STILL A FACTORY IN JAVA!
public static void main(String[] args) {


         JobFactory factory = new JdbcJobFactory();


               SCALA                       JAVA
         JobControl control = new JobControl(factory);

         ...
}
STILL A FACTORY IN JAVA!
public static void main(String[] args) {


         JobFactory factory = new JdbcJobFactory();

         JobControl control = new JobControl(factory);

         ...
}
IN CONCLUSION
You don’t have to use everything Scala has
            to offer right away!

You don’t even have to understand ALL the
  concepts of Scala to start coding Scala
IN CONCLUSION


It’s EASY to start programming Scala...
          It’s HARD to stop!
YOU HAVE BEEN WATCHING
YOU HAVE BEEN WATCHING
Enno Runne
email: enno@runne.net
                                              hlr ogge gical.com
                                      im O ogge@a
                                Joak .ohlr
                                 joa kim             ogge press.com
                                                 ohlr ord
                                            : @j
                                      itter lrogge.w
                                  tw
  http://a                           ttp:/ /joh
           gical.co                h
 http://a           m/reso
          gical.co         urces/a
 http://a          m/reso          r ticles/
          gical.co       urces/a             s4jp.pd
                  m/reso         r ticles/           f
                         urces/a           s4jp.m
                                 r ticles/         ov
                                          s4jp.ke
                                                   y

More Related Content

What's hot

Starting with Scala : Frontier Developer's Meetup December 2010
Starting with Scala : Frontier Developer's Meetup December 2010Starting with Scala : Frontier Developer's Meetup December 2010
Starting with Scala : Frontier Developer's Meetup December 2010Derek Chen-Becker
 
Functional Objects & Function and Closures
Functional Objects  & Function and ClosuresFunctional Objects  & Function and Closures
Functional Objects & Function and ClosuresSandip Kumar
 
Static or Dynamic Typing? Why not both?
Static or Dynamic Typing? Why not both?Static or Dynamic Typing? Why not both?
Static or Dynamic Typing? Why not both?Mario Camou Riveroll
 
Solid and Sustainable Development in Scala
Solid and Sustainable Development in ScalaSolid and Sustainable Development in Scala
Solid and Sustainable Development in Scalascalaconfjp
 
Scala Reflection & Runtime MetaProgramming
Scala Reflection & Runtime MetaProgrammingScala Reflection & Runtime MetaProgramming
Scala Reflection & Runtime MetaProgrammingMeir Maor
 
An Introduction to Scala for Java Developers
An Introduction to Scala for Java DevelopersAn Introduction to Scala for Java Developers
An Introduction to Scala for Java DevelopersMiles Sabin
 
pull requests I sent to scala/scala (ny-scala 2019)
pull requests I sent to scala/scala (ny-scala 2019)pull requests I sent to scala/scala (ny-scala 2019)
pull requests I sent to scala/scala (ny-scala 2019)Eugene Yokota
 
Scala for scripting
Scala for scriptingScala for scripting
Scala for scriptingmichid
 
Scala uma poderosa linguagem para a jvm
Scala   uma poderosa linguagem para a jvmScala   uma poderosa linguagem para a jvm
Scala uma poderosa linguagem para a jvmIsaias Barroso
 
An Introduction to Scala
An Introduction to ScalaAn Introduction to Scala
An Introduction to ScalaBrent Lemons
 

What's hot (20)

Scala introduction
Scala introductionScala introduction
Scala introduction
 
Starting with Scala : Frontier Developer's Meetup December 2010
Starting with Scala : Frontier Developer's Meetup December 2010Starting with Scala : Frontier Developer's Meetup December 2010
Starting with Scala : Frontier Developer's Meetup December 2010
 
All about scala
All about scalaAll about scala
All about scala
 
Functional Objects & Function and Closures
Functional Objects  & Function and ClosuresFunctional Objects  & Function and Closures
Functional Objects & Function and Closures
 
Static or Dynamic Typing? Why not both?
Static or Dynamic Typing? Why not both?Static or Dynamic Typing? Why not both?
Static or Dynamic Typing? Why not both?
 
Scala - brief intro
Scala - brief introScala - brief intro
Scala - brief intro
 
camel-scala.pdf
camel-scala.pdfcamel-scala.pdf
camel-scala.pdf
 
Scale up your thinking
Scale up your thinkingScale up your thinking
Scale up your thinking
 
Solid and Sustainable Development in Scala
Solid and Sustainable Development in ScalaSolid and Sustainable Development in Scala
Solid and Sustainable Development in Scala
 
Scala Reflection & Runtime MetaProgramming
Scala Reflection & Runtime MetaProgrammingScala Reflection & Runtime MetaProgramming
Scala Reflection & Runtime MetaProgramming
 
An Introduction to Scala for Java Developers
An Introduction to Scala for Java DevelopersAn Introduction to Scala for Java Developers
An Introduction to Scala for Java Developers
 
Java 7 New Features
Java 7 New FeaturesJava 7 New Features
Java 7 New Features
 
Scala presentationjune112011
Scala presentationjune112011Scala presentationjune112011
Scala presentationjune112011
 
pull requests I sent to scala/scala (ny-scala 2019)
pull requests I sent to scala/scala (ny-scala 2019)pull requests I sent to scala/scala (ny-scala 2019)
pull requests I sent to scala/scala (ny-scala 2019)
 
Java 5 and 6 New Features
Java 5 and 6 New FeaturesJava 5 and 6 New Features
Java 5 and 6 New Features
 
Functional java 8
Functional java 8Functional java 8
Functional java 8
 
Scala for scripting
Scala for scriptingScala for scripting
Scala for scripting
 
Scala uma poderosa linguagem para a jvm
Scala   uma poderosa linguagem para a jvmScala   uma poderosa linguagem para a jvm
Scala uma poderosa linguagem para a jvm
 
An Introduction to Scala
An Introduction to ScalaAn Introduction to Scala
An Introduction to Scala
 
Java scriptforjavadev part2a
Java scriptforjavadev part2aJava scriptforjavadev part2a
Java scriptforjavadev part2a
 

Viewers also liked

SOLID - Principles of Object Oriented Design
SOLID - Principles of Object Oriented DesignSOLID - Principles of Object Oriented Design
SOLID - Principles of Object Oriented DesignRiccardo Cardin
 
Java- Concurrent programming - Synchronization (part 2)
Java- Concurrent programming - Synchronization (part 2)Java- Concurrent programming - Synchronization (part 2)
Java- Concurrent programming - Synchronization (part 2)Riccardo Cardin
 
Java- Concurrent programming - Synchronization (part 1)
Java- Concurrent programming - Synchronization (part 1)Java- Concurrent programming - Synchronization (part 1)
Java- Concurrent programming - Synchronization (part 1)Riccardo Cardin
 
Java Graphics Programming
Java Graphics ProgrammingJava Graphics Programming
Java Graphics ProgrammingRiccardo Cardin
 
Design pattern architetturali Model View Controller, MVP e MVVM
Design pattern architetturali   Model View Controller, MVP e MVVMDesign pattern architetturali   Model View Controller, MVP e MVVM
Design pattern architetturali Model View Controller, MVP e MVVMRiccardo Cardin
 
A (too) Short Introduction to Scala
A (too) Short Introduction to ScalaA (too) Short Introduction to Scala
A (too) Short Introduction to ScalaRiccardo Cardin
 
Java - Processing input and output
Java - Processing input and outputJava - Processing input and output
Java - Processing input and outputRiccardo Cardin
 
Design Pattern Strutturali
Design Pattern StrutturaliDesign Pattern Strutturali
Design Pattern StrutturaliRiccardo Cardin
 
Java Exception Handling, Assertions and Logging
Java Exception Handling, Assertions and LoggingJava Exception Handling, Assertions and Logging
Java Exception Handling, Assertions and LoggingRiccardo Cardin
 
Java - Concurrent programming - Thread's advanced concepts
Java - Concurrent programming - Thread's advanced conceptsJava - Concurrent programming - Thread's advanced concepts
Java - Concurrent programming - Thread's advanced conceptsRiccardo Cardin
 
Java - Remote method invocation
Java - Remote method invocationJava - Remote method invocation
Java - Remote method invocationRiccardo Cardin
 
Software architecture patterns
Software architecture patternsSoftware architecture patterns
Software architecture patternsRiccardo Cardin
 
Introduzione ai Design Pattern
Introduzione ai Design PatternIntroduzione ai Design Pattern
Introduzione ai Design PatternRiccardo Cardin
 
Presto updates to 0.178
Presto updates to 0.178Presto updates to 0.178
Presto updates to 0.178Kai Sasaki
 
Errori comuni nei documenti di Analisi dei Requisiti
Errori comuni nei documenti di Analisi dei RequisitiErrori comuni nei documenti di Analisi dei Requisiti
Errori comuni nei documenti di Analisi dei RequisitiRiccardo Cardin
 
Java - Concurrent programming - Thread's basics
Java - Concurrent programming - Thread's basicsJava - Concurrent programming - Thread's basics
Java - Concurrent programming - Thread's basicsRiccardo Cardin
 
Scala - the good, the bad and the very ugly
Scala - the good, the bad and the very uglyScala - the good, the bad and the very ugly
Scala - the good, the bad and the very uglyBozhidar Bozhanov
 

Viewers also liked (20)

SOLID - Principles of Object Oriented Design
SOLID - Principles of Object Oriented DesignSOLID - Principles of Object Oriented Design
SOLID - Principles of Object Oriented Design
 
Java- Concurrent programming - Synchronization (part 2)
Java- Concurrent programming - Synchronization (part 2)Java- Concurrent programming - Synchronization (part 2)
Java- Concurrent programming - Synchronization (part 2)
 
Java- Concurrent programming - Synchronization (part 1)
Java- Concurrent programming - Synchronization (part 1)Java- Concurrent programming - Synchronization (part 1)
Java- Concurrent programming - Synchronization (part 1)
 
Java Graphics Programming
Java Graphics ProgrammingJava Graphics Programming
Java Graphics Programming
 
Design pattern architetturali Model View Controller, MVP e MVVM
Design pattern architetturali   Model View Controller, MVP e MVVMDesign pattern architetturali   Model View Controller, MVP e MVVM
Design pattern architetturali Model View Controller, MVP e MVVM
 
A (too) Short Introduction to Scala
A (too) Short Introduction to ScalaA (too) Short Introduction to Scala
A (too) Short Introduction to Scala
 
Java - Processing input and output
Java - Processing input and outputJava - Processing input and output
Java - Processing input and output
 
Design Pattern Strutturali
Design Pattern StrutturaliDesign Pattern Strutturali
Design Pattern Strutturali
 
Java Exception Handling, Assertions and Logging
Java Exception Handling, Assertions and LoggingJava Exception Handling, Assertions and Logging
Java Exception Handling, Assertions and Logging
 
Java - Concurrent programming - Thread's advanced concepts
Java - Concurrent programming - Thread's advanced conceptsJava - Concurrent programming - Thread's advanced concepts
Java - Concurrent programming - Thread's advanced concepts
 
Java - Remote method invocation
Java - Remote method invocationJava - Remote method invocation
Java - Remote method invocation
 
Software architecture patterns
Software architecture patternsSoftware architecture patterns
Software architecture patterns
 
Java - Sockets
Java - SocketsJava - Sockets
Java - Sockets
 
Diagrammi delle Classi
Diagrammi delle ClassiDiagrammi delle Classi
Diagrammi delle Classi
 
Introduzione ai Design Pattern
Introduzione ai Design PatternIntroduzione ai Design Pattern
Introduzione ai Design Pattern
 
Presto updates to 0.178
Presto updates to 0.178Presto updates to 0.178
Presto updates to 0.178
 
Errori comuni nei documenti di Analisi dei Requisiti
Errori comuni nei documenti di Analisi dei RequisitiErrori comuni nei documenti di Analisi dei Requisiti
Errori comuni nei documenti di Analisi dei Requisiti
 
Java - Concurrent programming - Thread's basics
Java - Concurrent programming - Thread's basicsJava - Concurrent programming - Thread's basics
Java - Concurrent programming - Thread's basics
 
Diagrammi di Sequenza
Diagrammi di SequenzaDiagrammi di Sequenza
Diagrammi di Sequenza
 
Scala - the good, the bad and the very ugly
Scala - the good, the bad and the very uglyScala - the good, the bad and the very ugly
Scala - the good, the bad and the very ugly
 

Similar to Scala For Java Programmers

Google Guava for cleaner code
Google Guava for cleaner codeGoogle Guava for cleaner code
Google Guava for cleaner codeMite Mitreski
 
Building Smart Async Functions For Mobile
Building Smart Async Functions For MobileBuilding Smart Async Functions For Mobile
Building Smart Async Functions For MobileGlan Thomas
 
1.2 scala basics
1.2 scala basics1.2 scala basics
1.2 scala basicswpgreenway
 
2.1 recap from-day_one
2.1 recap from-day_one2.1 recap from-day_one
2.1 recap from-day_onefuturespective
 
CodeCamp Iasi 10 march 2012 - Practical Groovy
CodeCamp Iasi 10 march 2012 - Practical GroovyCodeCamp Iasi 10 march 2012 - Practical Groovy
CodeCamp Iasi 10 march 2012 - Practical GroovyCodecamp Romania
 
Type script, for dummies
Type script, for dummiesType script, for dummies
Type script, for dummiessantiagoaguiar
 
LinkedIn TBC JavaScript 100: Functions
 LinkedIn TBC JavaScript 100: Functions LinkedIn TBC JavaScript 100: Functions
LinkedIn TBC JavaScript 100: FunctionsAdam Crabtree
 
Scala - en bedre og mere effektiv Java?
Scala - en bedre og mere effektiv Java?Scala - en bedre og mere effektiv Java?
Scala - en bedre og mere effektiv Java?Jesper Kamstrup Linnet
 
Kotlin Advanced - Apalon Kotlin Sprint Part 3
Kotlin Advanced - Apalon Kotlin Sprint Part 3Kotlin Advanced - Apalon Kotlin Sprint Part 3
Kotlin Advanced - Apalon Kotlin Sprint Part 3Kirill Rozov
 
Intro to scala
Intro to scalaIntro to scala
Intro to scalaJoe Zulli
 
BCS SPA 2010 - An Introduction to Scala for Java Developers
BCS SPA 2010 - An Introduction to Scala for Java DevelopersBCS SPA 2010 - An Introduction to Scala for Java Developers
BCS SPA 2010 - An Introduction to Scala for Java DevelopersMiles Sabin
 

Similar to Scala For Java Programmers (20)

Google Guava for cleaner code
Google Guava for cleaner codeGoogle Guava for cleaner code
Google Guava for cleaner code
 
Beyond java8
Beyond java8Beyond java8
Beyond java8
 
Alternate JVM Languages
Alternate JVM LanguagesAlternate JVM Languages
Alternate JVM Languages
 
JS OO and Closures
JS OO and ClosuresJS OO and Closures
JS OO and Closures
 
Building Smart Async Functions For Mobile
Building Smart Async Functions For MobileBuilding Smart Async Functions For Mobile
Building Smart Async Functions For Mobile
 
Presentatie - Introductie in Groovy
Presentatie - Introductie in GroovyPresentatie - Introductie in Groovy
Presentatie - Introductie in Groovy
 
1.2 scala basics
1.2 scala basics1.2 scala basics
1.2 scala basics
 
1.2 scala basics
1.2 scala basics1.2 scala basics
1.2 scala basics
 
2.1 recap from-day_one
2.1 recap from-day_one2.1 recap from-day_one
2.1 recap from-day_one
 
CodeCamp Iasi 10 march 2012 - Practical Groovy
CodeCamp Iasi 10 march 2012 - Practical GroovyCodeCamp Iasi 10 march 2012 - Practical Groovy
CodeCamp Iasi 10 march 2012 - Practical Groovy
 
Scala - en bedre Java?
Scala - en bedre Java?Scala - en bedre Java?
Scala - en bedre Java?
 
Type script, for dummies
Type script, for dummiesType script, for dummies
Type script, for dummies
 
LinkedIn TBC JavaScript 100: Functions
 LinkedIn TBC JavaScript 100: Functions LinkedIn TBC JavaScript 100: Functions
LinkedIn TBC JavaScript 100: Functions
 
Scala - en bedre og mere effektiv Java?
Scala - en bedre og mere effektiv Java?Scala - en bedre og mere effektiv Java?
Scala - en bedre og mere effektiv Java?
 
Kotlin Advanced - Apalon Kotlin Sprint Part 3
Kotlin Advanced - Apalon Kotlin Sprint Part 3Kotlin Advanced - Apalon Kotlin Sprint Part 3
Kotlin Advanced - Apalon Kotlin Sprint Part 3
 
Pattern Matching in Java 14
Pattern Matching in Java 14Pattern Matching in Java 14
Pattern Matching in Java 14
 
Scala in practice
Scala in practiceScala in practice
Scala in practice
 
25-functions.ppt
25-functions.ppt25-functions.ppt
25-functions.ppt
 
Intro to scala
Intro to scalaIntro to scala
Intro to scala
 
BCS SPA 2010 - An Introduction to Scala for Java Developers
BCS SPA 2010 - An Introduction to Scala for Java DevelopersBCS SPA 2010 - An Introduction to Scala for Java Developers
BCS SPA 2010 - An Introduction to Scala for Java Developers
 

More from Enno Runne

Let the alpakka pull your stream
Let the alpakka pull your streamLet the alpakka pull your stream
Let the alpakka pull your streamEnno Runne
 
From Overnight to Always On @ Jfokus 2019
From Overnight to Always On @ Jfokus 2019From Overnight to Always On @ Jfokus 2019
From Overnight to Always On @ Jfokus 2019Enno Runne
 
Always on. 2018-10 Reactive Summit
Always on. 2018-10 Reactive SummitAlways on. 2018-10 Reactive Summit
Always on. 2018-10 Reactive SummitEnno Runne
 
Webinar Alpakka 2018-08-16
Webinar Alpakka 2018-08-16Webinar Alpakka 2018-08-16
Webinar Alpakka 2018-08-16Enno Runne
 
Programming in pain
Programming in painProgramming in pain
Programming in painEnno Runne
 

More from Enno Runne (6)

Let the alpakka pull your stream
Let the alpakka pull your streamLet the alpakka pull your stream
Let the alpakka pull your stream
 
From Overnight to Always On @ Jfokus 2019
From Overnight to Always On @ Jfokus 2019From Overnight to Always On @ Jfokus 2019
From Overnight to Always On @ Jfokus 2019
 
Always on. 2018-10 Reactive Summit
Always on. 2018-10 Reactive SummitAlways on. 2018-10 Reactive Summit
Always on. 2018-10 Reactive Summit
 
Webinar Alpakka 2018-08-16
Webinar Alpakka 2018-08-16Webinar Alpakka 2018-08-16
Webinar Alpakka 2018-08-16
 
Programming in pain
Programming in painProgramming in pain
Programming in pain
 
Real generics
Real genericsReal generics
Real generics
 

Recently uploaded

Spring24-Release Overview - Wellingtion User Group-1.pdf
Spring24-Release Overview - Wellingtion User Group-1.pdfSpring24-Release Overview - Wellingtion User Group-1.pdf
Spring24-Release Overview - Wellingtion User Group-1.pdfAnna Loughnan Colquhoun
 
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...UbiTrack UK
 
Do we need a new standard for visualizing the invisible?
Do we need a new standard for visualizing the invisible?Do we need a new standard for visualizing the invisible?
Do we need a new standard for visualizing the invisible?SANGHEE SHIN
 
Computer 10: Lesson 10 - Online Crimes and Hazards
Computer 10: Lesson 10 - Online Crimes and HazardsComputer 10: Lesson 10 - Online Crimes and Hazards
Computer 10: Lesson 10 - Online Crimes and HazardsSeth Reyes
 
Digital magic. A small project for controlling smart light bulbs.
Digital magic. A small project for controlling smart light bulbs.Digital magic. A small project for controlling smart light bulbs.
Digital magic. A small project for controlling smart light bulbs.francesco barbera
 
COMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online CollaborationCOMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online Collaborationbruanjhuli
 
Crea il tuo assistente AI con lo Stregatto (open source python framework)
Crea il tuo assistente AI con lo Stregatto (open source python framework)Crea il tuo assistente AI con lo Stregatto (open source python framework)
Crea il tuo assistente AI con lo Stregatto (open source python framework)Commit University
 
KubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCost
KubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCostKubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCost
KubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCostMatt Ray
 
Secure your environment with UiPath and CyberArk technologies - Session 1
Secure your environment with UiPath and CyberArk technologies - Session 1Secure your environment with UiPath and CyberArk technologies - Session 1
Secure your environment with UiPath and CyberArk technologies - Session 1DianaGray10
 
RAG Patterns and Vector Search in Generative AI
RAG Patterns and Vector Search in Generative AIRAG Patterns and Vector Search in Generative AI
RAG Patterns and Vector Search in Generative AIUdaiappa Ramachandran
 
Machine Learning Model Validation (Aijun Zhang 2024).pdf
Machine Learning Model Validation (Aijun Zhang 2024).pdfMachine Learning Model Validation (Aijun Zhang 2024).pdf
Machine Learning Model Validation (Aijun Zhang 2024).pdfAijun Zhang
 
Cybersecurity Workshop #1.pptx
Cybersecurity Workshop #1.pptxCybersecurity Workshop #1.pptx
Cybersecurity Workshop #1.pptxGDSC PJATK
 
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019IES VE
 
Introduction to Quantum Computing
Introduction to Quantum ComputingIntroduction to Quantum Computing
Introduction to Quantum ComputingGDSC PJATK
 
Nanopower In Semiconductor Industry.pdf
Nanopower  In Semiconductor Industry.pdfNanopower  In Semiconductor Industry.pdf
Nanopower In Semiconductor Industry.pdfPedro Manuel
 
Basic Building Blocks of Internet of Things.
Basic Building Blocks of Internet of Things.Basic Building Blocks of Internet of Things.
Basic Building Blocks of Internet of Things.YounusS2
 
Introduction to Matsuo Laboratory (ENG).pptx
Introduction to Matsuo Laboratory (ENG).pptxIntroduction to Matsuo Laboratory (ENG).pptx
Introduction to Matsuo Laboratory (ENG).pptxMatsuo Lab
 
Anypoint Code Builder , Google Pub sub connector and MuleSoft RPA
Anypoint Code Builder , Google Pub sub connector and MuleSoft RPAAnypoint Code Builder , Google Pub sub connector and MuleSoft RPA
Anypoint Code Builder , Google Pub sub connector and MuleSoft RPAshyamraj55
 
Linked Data in Production: Moving Beyond Ontologies
Linked Data in Production: Moving Beyond OntologiesLinked Data in Production: Moving Beyond Ontologies
Linked Data in Production: Moving Beyond OntologiesDavid Newbury
 
UiPath Studio Web workshop series - Day 8
UiPath Studio Web workshop series - Day 8UiPath Studio Web workshop series - Day 8
UiPath Studio Web workshop series - Day 8DianaGray10
 

Recently uploaded (20)

Spring24-Release Overview - Wellingtion User Group-1.pdf
Spring24-Release Overview - Wellingtion User Group-1.pdfSpring24-Release Overview - Wellingtion User Group-1.pdf
Spring24-Release Overview - Wellingtion User Group-1.pdf
 
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
 
Do we need a new standard for visualizing the invisible?
Do we need a new standard for visualizing the invisible?Do we need a new standard for visualizing the invisible?
Do we need a new standard for visualizing the invisible?
 
Computer 10: Lesson 10 - Online Crimes and Hazards
Computer 10: Lesson 10 - Online Crimes and HazardsComputer 10: Lesson 10 - Online Crimes and Hazards
Computer 10: Lesson 10 - Online Crimes and Hazards
 
Digital magic. A small project for controlling smart light bulbs.
Digital magic. A small project for controlling smart light bulbs.Digital magic. A small project for controlling smart light bulbs.
Digital magic. A small project for controlling smart light bulbs.
 
COMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online CollaborationCOMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online Collaboration
 
Crea il tuo assistente AI con lo Stregatto (open source python framework)
Crea il tuo assistente AI con lo Stregatto (open source python framework)Crea il tuo assistente AI con lo Stregatto (open source python framework)
Crea il tuo assistente AI con lo Stregatto (open source python framework)
 
KubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCost
KubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCostKubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCost
KubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCost
 
Secure your environment with UiPath and CyberArk technologies - Session 1
Secure your environment with UiPath and CyberArk technologies - Session 1Secure your environment with UiPath and CyberArk technologies - Session 1
Secure your environment with UiPath and CyberArk technologies - Session 1
 
RAG Patterns and Vector Search in Generative AI
RAG Patterns and Vector Search in Generative AIRAG Patterns and Vector Search in Generative AI
RAG Patterns and Vector Search in Generative AI
 
Machine Learning Model Validation (Aijun Zhang 2024).pdf
Machine Learning Model Validation (Aijun Zhang 2024).pdfMachine Learning Model Validation (Aijun Zhang 2024).pdf
Machine Learning Model Validation (Aijun Zhang 2024).pdf
 
Cybersecurity Workshop #1.pptx
Cybersecurity Workshop #1.pptxCybersecurity Workshop #1.pptx
Cybersecurity Workshop #1.pptx
 
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
 
Introduction to Quantum Computing
Introduction to Quantum ComputingIntroduction to Quantum Computing
Introduction to Quantum Computing
 
Nanopower In Semiconductor Industry.pdf
Nanopower  In Semiconductor Industry.pdfNanopower  In Semiconductor Industry.pdf
Nanopower In Semiconductor Industry.pdf
 
Basic Building Blocks of Internet of Things.
Basic Building Blocks of Internet of Things.Basic Building Blocks of Internet of Things.
Basic Building Blocks of Internet of Things.
 
Introduction to Matsuo Laboratory (ENG).pptx
Introduction to Matsuo Laboratory (ENG).pptxIntroduction to Matsuo Laboratory (ENG).pptx
Introduction to Matsuo Laboratory (ENG).pptx
 
Anypoint Code Builder , Google Pub sub connector and MuleSoft RPA
Anypoint Code Builder , Google Pub sub connector and MuleSoft RPAAnypoint Code Builder , Google Pub sub connector and MuleSoft RPA
Anypoint Code Builder , Google Pub sub connector and MuleSoft RPA
 
Linked Data in Production: Moving Beyond Ontologies
Linked Data in Production: Moving Beyond OntologiesLinked Data in Production: Moving Beyond Ontologies
Linked Data in Production: Moving Beyond Ontologies
 
UiPath Studio Web workshop series - Day 8
UiPath Studio Web workshop series - Day 8UiPath Studio Web workshop series - Day 8
UiPath Studio Web workshop series - Day 8
 

Scala For Java Programmers

  • 1. SCALA FOR JAVA PROGRAMMERS
  • 2. AGENDA 1. Object orientation (OO) 2. Functional programming (FP) 1.1 Every value is an object 2.1 Every function is a value 1.2 Mixin-based composition with traits 2.2 Anonymous functions 1.3 Self-type annotations 2.3 Higher-order functions 1.4 Structural typing 2.4 Closures 1.5 Local type inference 2.5 Currying 1.6 Static type system 2.6 Immutability 1.7 Generic classes 2.7 For comprehensions 1.8 Variance annotations 2.8 Algebraic data types 1.9 Upper and lower type bounds 2.9 Pattern matching 1.10 Inner classes and abstract types as object members 3. Practice 1.12 Compound types 1.13 Explicitly typed self references 3.1 Square roots using Newtons method 1.14 Views, and polymorphic methods. 3.2 Finding fixed points
  • 4. WHAT WE (REALLY) WANT YOU TO LEARN: •A Java to Scala conversion is easy • Scala brings a lot of new possibilities • You don’t have to understand all new possibilities to start with
  • 5. JAVA ➟ SCALA LET’S START WITH A WARM-UP
  • 6. OUR ALL JAVA MAIN Defined in Java public static void main(String[] args) { JobFactory factory = new JdbcJobFactory(); JobControl control = new JobControl(factory); ... }
  • 7. PROJECT LAYOUT Java Application Module
  • 8. PROJECT LAYOUT Java Java Application Module
  • 9. PROJECT LAYOUT Java Scala Java Application Module Module
  • 10. PROJECT LAYOUT Job.java Java Scala Java Application Module Module
  • 11. PROJECT LAYOUT Job.scala Java Scala Java Application Module Module
  • 12. public class Job { private String name; private List<Step> steps; private Map<String, Object> args; public Map<String, Object> getArgs() { return args; } public void setArgs(Map<String, Object> args) { this.args = args; } public List<Step> getSteps() { return steps; } public void setSteps(List<Step> steps) { this.steps = steps; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
  • 13. public class Job { private String name; Make it compile private List<Step> steps; private Map<String, Object> args; •Public is default public Map<String, Object> getArgs() { •Variables are return args; declared with var } public void setArgs(Map<String, Object> args) { •Types after identifier •Generics with [] this.args = args; } public List<Step> getSteps() { return steps; •Functions declared } public void setSteps(List<Step> steps) { with def this.steps = steps; } •= {...} public String getName() { return name; •void ≈ Unit } •initialize var public void setName(String name) { this.name = name; } }
  • 14. class Job { private String name; Make it compile private List<Step> steps; private Map<String, Object> args; •Public is default Map<String, Object> getArgs() { •Variables are return args; declared with var } void setArgs(Map<String, Object> args) { •Types after identifier •Generics with [] this.args = args; } List<Step> getSteps() { return steps; •Functions declared } void setSteps(List<Step> steps) { with def this.steps = steps; } •= {...} String getName() { return name; •void ≈ Unit } •initialize var void setName(String name) { this.name = name; } }
  • 15. class Job { private String name; Make it compile private List<Step> steps; private Map<String, Object> args; •Public is default Map<String, Object> getArgs() { •Variables are return args; declared with var } void setArgs(Map<String, Object> args) { •Types after identifier •Generics with [] this.args = args; } List<Step> getSteps() { return steps; •Functions declared } void setSteps(List<Step> steps) { with def this.steps = steps; } •= {...} String getName() { return name; •void ≈ Unit } •initialize var void setName(String name) { this.name = name; } }
  • 16. class Job { private String name; Make it compile private List<Step> steps; private Map<String, Object> args; •Public is default Map<String, Object> getArgs() { •Variables are return args; declared with var } void setArgs(Map<String, Object> args) { •Types after identifier •Generics with [] this.args = args; } List<Step> getSteps() { return steps; •Functions declared } void setSteps(List<Step> steps) { with def this.steps = steps; } •= {...} String getName() { return name; •void ≈ Unit } •initialize var void setName(String name) { this.name = name; } }
  • 17. class Job { private var String name; Make it compile private var List<Step> steps; private var Map<String, Object> args; •Public is default Map<String, Object> getArgs() { •Variables are return args; declared with var } void setArgs(Map<String, Object> args) { •Types after identifier •Generics with [] this.args = args; } List<Step> getSteps() { return steps; •Functions declared } void setSteps(List<Step> steps) { with def this.steps = steps; } •= {...} String getName() { return name; •void ≈ Unit } •initialize var void setName(String name) { this.name = name; } }
  • 18. class Job { private var String name; Make it compile private var List<Step> steps; private var Map<String, Object> args; •Public is default Map<String, Object> getArgs() { •Variables are return args; declared with var } void setArgs(Map<String, Object> args) { •Types after identifier •Generics with [] this.args = args; } List<Step> getSteps() { return steps; •Functions declared } void setSteps(List<Step> steps) { with def this.steps = steps; } •= {...} String getName() { return name; •void ≈ Unit } •initialize var void setName(String name) { this.name = name; } }
  • 19. class Job { private var String name; Make it compile private var List<Step> steps; private var Map<String, Object> args; •Public is default Map<String, Object> getArgs() { •Variables are return args; declared with var } void setArgs(Map<String, Object> args) { •Types after identifier •Generics with [] this.args = args; } List<Step> getSteps() { return steps; •Functions declared } void setSteps(List<Step> steps) { with def this.steps = steps; } •= {...} String getName() { return name; •void ≈ Unit } •initialize var void setName(String name) { this.name = name; } }
  • 20. class Job { private var name:String; Make it compile private var steps:List<Step>; private var args:Map<String, Object>; •Public is default getArgs():Map<String, Object> { •Variables are return args; declared with var } setArgs(args:Map<String, Object>):void { •Types after identifier •Generics with [] this.args = args; } getSteps():List<Step> { return steps; •Functions declared } setSteps(steps:List<Step>):void { with def this.steps = steps; } •= {...} getName():String { return name; •void ≈ Unit } •initialize var setName(name:String):void { this.name = name; } }
  • 21. class Job { private var name:String; Make it compile private var steps:List<Step>; private var args:Map<String, Object>; •Public is default getArgs():Map<String, Object> { •Variables are return args; declared with var } setArgs(args:Map<String, Object>):void { •Types after identifier •Generics with [] this.args = args; } getSteps():List<Step> { return steps; •Functions declared } setSteps(steps:List<Step>):void { with def this.steps = steps; } •= {...} getName():String { return name; •void ≈ Unit } •initialize var setName(name:String):void { this.name = name; } }
  • 22. class Job { private var name:String; Make it compile private var steps:List<Step>; private var args:Map<String, Object>; •Public is default getArgs():Map<String, Object> { •Variables are return args; declared with var } setArgs(args:Map<String, Object>):void { •Types after identifier •Generics with [] this.args = args; } getSteps():List<Step> { return steps; •Functions declared } setSteps(steps:List<Step>):void { with def this.steps = steps; } •= {...} getName():String { return name; •void ≈ Unit } •initialize var setName(name:String):void { this.name = name; } }
  • 23. class Job { private var name:String; Make it compile private var steps:List[Step]; private var args:Map[String, Object]; •Public is default getArgs():Map[String, Object] { •Variables are return args; declared with var } setArgs(args:Map[String, Object]):void { •Types after identifier •Generics with [] this.args = args; } getSteps():List[Step] { return steps; •Functions declared } setSteps(steps:List[Step]):void { with def this.steps = steps; } •= {...} getName():String { return name; •void ≈ Unit } •initialize var setName(name:String):void { this.name = name; } }
  • 24. class Job { private var name:String; Make it compile private var steps:List[Step]; private var args:Map[String, Object]; •Public is default getArgs():Map[String, Object] { •Variables are return args; declared with var } setArgs(args:Map[String, Object]):void { •Types after identifier •Generics with [] this.args = args; } getSteps():List[Step] { return steps; •Functions declared } setSteps(steps:List[Step]):void { with def this.steps = steps; } •= {...} getName():String { return name; •void ≈ Unit } •initialize var setName(name:String):void { this.name = name; } }
  • 25. class Job { private var name:String; Make it compile private var steps:List[Step]; private var args:Map[String, Object]; •Public is default getArgs():Map[String, Object] { •Variables are return args; declared with var } setArgs(args:Map[String, Object]):void { •Types after identifier •Generics with [] this.args = args; } getSteps():List[Step] { return steps; •Functions declared } setSteps(steps:List[Step]):void { with def this.steps = steps; } •= {...} getName():String { return name; •void ≈ Unit } •initialize var setName(name:String):void { this.name = name; } }
  • 26. class Job { private var name:String; Make it compile private var steps:List[Step]; private var args:Map[String, Object]; •Public is default def getArgs():Map[String, Object] { •Variables are return args; declared with var } def setArgs(args:Map[String, Object]):void { •Types after identifier •Generics with [] this.args = args; } def getSteps():List[Step] { return steps; •Functions declared } def setSteps(steps:List[Step]):void { with def this.steps = steps; } •= {...} def getName():String { return name; •void ≈ Unit } •initialize var def setName(name:String):void { this.name = name; } }
  • 27. class Job { private var name:String; Make it compile private var steps:List[Step]; private var args:Map[String, Object]; •Public is default def getArgs():Map[String, Object] { •Variables are return args; declared with var } def setArgs(args:Map[String, Object]):void { •Types after identifier •Generics with [] this.args = args; } def getSteps():List[Step] { return steps; •Functions declared } def setSteps(steps:List[Step]):void { with def this.steps = steps; } •= {...} def getName():String { return name; •void ≈ Unit } •initialize var def setName(name:String):void { this.name = name; } }
  • 28. class Job { private var name:String; Make it compile private var steps:List[Step]; private var args:Map[String, Object]; •Public is default def getArgs():Map[String, Object] { •Variables are return args; declared with var } def setArgs(args:Map[String, Object]):void { •Types after identifier •Generics with [] this.args = args; } def getSteps():List[Step] { return steps; •Functions declared } def setSteps(steps:List[Step]):void { with def this.steps = steps; } •= {...} def getName():String { return name; •void ≈ Unit } •initialize var def setName(name:String):void { this.name = name; } }
  • 29. class Job { private var name:String; Make it compile private var steps:List[Step]; private var args:Map[String, Object]; •Public is default def getArgs():Map[String, Object] { •Variables are return args; declared with var } def setArgs(args:Map[String, Object]):void { •Types after identifier •Generics with [] this.args = args; } def getSteps():List[Step] { return steps; •Functions declared } def setSteps(steps:List[Step]):void { with def this.steps = steps; } •= {...} def getName():String { return name; •void ≈ Unit } •initialize var def setName(name:String):void { this.name = name; } }
  • 30. class Job { private var name:String; Make it compile private var steps:List[Step]; private var args:Map[String, Object]; •Public is default def getArgs():Map[String, Object] = { •Variables are return args; declared with var } def setArgs(args:Map[String, Object]):void = { •Types after identifier •Generics with [] this.args = args; } def getSteps():List[Step] = { return steps; •Functions declared } def setSteps(steps:List[Step]):void = { with def this.steps = steps; } •= {...} def getName():String = { return name; •void ≈ Unit } •initialize var def setName(name:String):void = { this.name = name; } }
  • 31. class Job { private var name:String; Make it compile private var steps:List[Step]; private var args:Map[String, Object]; •Public is default def getArgs():Map[String, Object] = { •Variables are return args; declared with var } def setArgs(args:Map[String, Object]):void = { •Types after identifier •Generics with [] this.args = args; } def getSteps():List[Step] = { return steps; •Functions declared } def setSteps(steps:List[Step]):void = { with def this.steps = steps; } •= {...} def getName():String = { return name; •void ≈ Unit } •initialize var def setName(name:String):void = { this.name = name; } }
  • 32. class Job { private var name:String; Make it compile private var steps:List[Step]; private var args:Map[String, Object]; •Public is default def getArgs():Map[String, Object] = { •Variables are return args; declared with var } def setArgs(args:Map[String, Object]):void = { •Types after identifier •Generics with [] this.args = args; } def getSteps():List[Step] = { return steps; •Functions declared } def setSteps(steps:List[Step]):void = { with def this.steps = steps; } •= {...} def getName():String = { return name; •void ≈ Unit } •initialize var def setName(name:String):void = { this.name = name; } }
  • 33. class Job { private var name:String; Make it compile private var steps:List[Step]; private var args:Map[String, Object]; •Public is default def getArgs():Map[String, Object] = { •Variables are return args; declared with var } def setArgs(args:Map[String, Object]):void = { •Types after identifier •Generics with [] this.args = args; } def getSteps():List[Step] = { return steps; •Functions declared } def setSteps(steps:List[Step]):void = { with def this.steps = steps; } •= {...} def getName():String = { return name; •void ≈ Unit } •initialize var def setName(name:String):void = { this.name = name; } }
  • 34. class Job { private var name:String; Make it compile private var steps:List[Step]; private var args:Map[String, Object]; •Public is default def getArgs():Map[String, Object] = { •Variables are return args; declared with var } def setArgs(args:Map[String, Object]):Unit = { •Types after identifier •Generics with [] this.args = args; } def getSteps():List[Step] = { return steps; •Functions declared } def setSteps(steps:List[Step]):Unit = { with def this.steps = steps; } •= {...} def getName():String = { return name; •void ≈ Unit } •initialize var def setName(name:String):Unit = { this.name = name; } }
  • 35. class Job { private var name:String; Make it compile private var steps:List[Step]; private var args:Map[String, Object]; •Public is default def getArgs():Map[String, Object] = { •Variables are return args; declared with var } def setArgs(args:Map[String, Object]):Unit = { •Types after identifier •Generics with [] this.args = args; } def getSteps():List[Step] = { return steps; •Functions declared } def setSteps(steps:List[Step]):Unit = { with def this.steps = steps; } •= {...} def getName():String = { return name; •void ≈ Unit } •initialize var def setName(name:String):Unit = { this.name = name; } }
  • 36. class Job { private var name:String; Make it compile private var steps:List[Step]; private var args:Map[String, Object]; •Public is default def getArgs():Map[String, Object] = { •Variables are return args; declared with var } def setArgs(args:Map[String, Object]):Unit = { •Types after identifier •Generics with [] this.args = args; } def getSteps():List[Step] = { return steps; •Functions declared } def setSteps(steps:List[Step]):Unit = { with def this.steps = steps; } •= {...} def getName():String = { return name; •void ≈ Unit } •initialize var def setName(name:String):Unit = { this.name = name; } }
  • 37. class Job { private var name:String; Make it compile private var steps:List[Step]; private var args:Map[String, Object]; •Public is default def getArgs():Map[String, Object] = { •Variables are return args; declared with var } def setArgs(args:Map[String, Object]):Unit = { •Types after identifier •Generics with [] this.args = args; } def getSteps():List[Step] = { return steps; •Functions declared } def setSteps(steps:List[Step]):Unit = { with def this.steps = steps; } •= {...} def getName():String = { return name; •void ≈ Unit } •initialize var def setName(name:String):Unit = { this.name = name; } }
  • 38. class Job { private var name:String = null; Make it compile private var steps:List[Step] = null; private var args:Map[String, Object] = null; •Public is default def getArgs():Map[String, Object] = { •Variables are return args; declared with var } def setArgs(args:Map[String, Object]):Unit = { •Types after identifier •Generics with [] this.args = args; } def getSteps():List[Step] = { return steps; •Functions declared } def setSteps(steps:List[Step]):Unit = { with def this.steps = steps; } •= {...} def getName():String = { return name; •void ≈ Unit } •initialize var def setName(name:String):Unit = { this.name = name; } }
  • 39. class Job { private var name:String = null; Make it compile private var steps:List[Step] = null; private var args:Map[String, Object] = null; •Public is default def getArgs():Map[String, Object] = { •Variables are return args; declared with var } def setArgs(args:Map[String, Object]):Unit = { •Types after identifier •Generics with [] this.args = args; } def getSteps():List[Step] = { return steps; •Functions declared } def setSteps(steps:List[Step]):Unit = { with def this.steps = steps; } •= {...} def getName():String = { return name; •void ≈ Unit } •initialize var def setName(name:String):Unit = { this.name = name; } }
  • 40. class Job { private var name:String = null; Make it compile private var steps:List[Step] = null; private var args:Map[String, Object] = null; •Public is default def getArgs():Map[String, Object] = { •Variables are return args; declared with var } def setArgs(args:Map[String, Object]):Unit = { •Types after identifier •Generics with [] this.args = args; } def getSteps():List[Step] = { return steps; •Functions declared } def setSteps(steps:List[Step]):Unit = { with def this.steps = steps; } •= {...} def getName():String = { return name; •void ≈ Unit } •initialize var def setName(name:String):Unit = { this.name = name; } }
  • 41. class Job { private var name:String = null; Make it compile private var steps:List[Step] = null; private var args:Map[String, Object] = null; •Public is default def getArgs():Map[String, Object] = { •Variables are return args; declared with var } def setArgs(args:Map[String, Object]):Unit = { •Types after identifier •Generics with [] this.args = args; } def getSteps():List[Step] = { return steps; •Functions declared } def setSteps(steps:List[Step]):Unit = { with def this.steps = steps; } •= {...} def getName():String = { return name; •void ≈ Unit } •initialize var def setName(name:String):Unit = { this.name = name; } }
  • 42. class Job { private var name:String = null; Make it compile private var steps:List[Step] = null; •Public is default private var args:Map[String, Object] = null; def getArgs():Map[String, Object] = { •Variables are return args; declared with var } •Types after identifier def setArgs(args:Map[String, Object]):Unit = { •Generics with [] this.args = args; } IT COMPILES def getSteps():List[Step] = { return steps; •Functions declared } BUT IT’S JAVA WITH SCALA SYNTAX with def def setSteps(steps:List[Step]):Unit = { this.steps = steps; } •= {...} def getName():String = { return name; •void ≈ Unit } •initialize var def setName(name:String):Unit = { this.name = name; } }
  • 43. class Job { private var name:String = null; Remove redundancy private var steps:List[Step] = null; private var args:Map[String, Object] = null; •The last statement is def getArgs():Map[String, Object] = { returned return args; } •Types are inferred def setArgs(args:Map[String, Object]):Unit = { •No = implies Unit •Single statement this.args = args; } def getSteps():List[Step] = { return steps; doesn’t need a block } def setSteps(steps:List[Step]):Unit = { •New line implies ; this.steps = steps; } def getName():String = { return name; } def setName(name:String):Unit = { this.name = name; } }
  • 44. class Job { private var name:String = null; Remove redundancy private var steps:List[Step] = null; private var args:Map[String, Object] = null; •The last statement is def getArgs():Map[String, Object] = { returned return args; } •Types are inferred def setArgs(args:Map[String, Object]):Unit = { •No = implies Unit •Single statement this.args = args; } def getSteps():List[Step] = { return steps; doesn’t need a block } def setSteps(steps:List[Step]):Unit = { •New line implies ; this.steps = steps; } def getName():String = { return name; } def setName(name:String):Unit = { this.name = name; } }
  • 45. class Job { private var name:String = null; Remove redundancy private var steps:List[Step] = null; private var args:Map[String, Object] = null; •The last statement is def getArgs():Map[String, Object] = { returned return args; } •Types are inferred def setArgs(args:Map[String, Object]):Unit = { •No = implies Unit •Single statement this.args = args; } def getSteps():List[Step] = { return steps; doesn’t need a block } def setSteps(steps:List[Step]):Unit = { •New line implies ; this.steps = steps; } def getName():String = { return name; } def setName(name:String):Unit = { this.name = name; } }
  • 46. class Job { private var name:String = null; Remove redundancy private var steps:List[Step] = null; private var args:Map[String, Object] = null; •The last statement is def getArgs():Map[String, Object] = { returned args; } •Types are inferred def setArgs(args:Map[String, Object]):Unit = { •No = implies Unit •Single statement this.args = args; } def getSteps():List[Step] = { steps; doesn’t need a block } def setSteps(steps:List[Step]):Unit = { •New line implies ; this.steps = steps; } def getName():String = { name; } def setName(name:String):Unit = { this.name = name; } }
  • 47. class Job { private var name:String = null; Remove redundancy private var steps:List[Step] = null; private var args:Map[String, Object] = null; •The last statement is def getArgs():Map[String, Object] = { returned args; } •Types are inferred def setArgs(args:Map[String, Object]):Unit = { •No = implies Unit •Single statement this.args = args; } def getSteps():List[Step] = { steps; doesn’t need a block } def setSteps(steps:List[Step]):Unit = { •New line implies ; this.steps = steps; } def getName():String = { name; } def setName(name:String):Unit = { this.name = name; } }
  • 48. class Job { private var name:String = null; Remove redundancy private var steps:List[Step] = null; private var args:Map[String, Object] = null; •The last statement is def getArgs() = { returned args; } •Types are inferred def setArgs(args:Map[String, Object]):Unit = { •No = implies Unit •Single statement this.args = args; } def getSteps() = { steps; doesn’t need a block } def setSteps(steps:List[Step]):Unit = { •New line implies ; this.steps = steps; } def getName() = { name; } def setName(name:String):Unit = { this.name = name; } }
  • 49. class Job { private var name:String = null; Remove redundancy private var steps:List[Step] = null; private var args:Map[String, Object] = null; •The last statement is def getArgs() = { returned args; } •Types are inferred def setArgs(args:Map[String, Object]):Unit = { •No = implies Unit •Single statement this.args = args; } def getSteps() = { steps; doesn’t need a block } def setSteps(steps:List[Step]):Unit = { •New line implies ; this.steps = steps; } def getName() = { name; } def setName(name:String):Unit = { this.name = name; } }
  • 50. class Job { private var name:String = null; Remove redundancy private var steps:List[Step] = null; private var args:Map[String, Object] = null; •The last statement is def getArgs() = { returned args; } •Types are inferred def setArgs(args:Map[String, Object]) { •No = implies Unit •Single statement this.args = args; } def getSteps() = { steps; doesn’t need a block } def setSteps(steps:List[Step]) { •New line implies ; this.steps = steps; } def getName() = { name; } def setName(name:String) { this.name = name; } }
  • 51. class Job { private var name:String = null; Remove redundancy private var steps:List[Step] = null; private var args:Map[String, Object] = null; •The last statement is def getArgs() = { returned args; } •Types are inferred def setArgs(args:Map[String, Object]) { •No = implies Unit •Single statement this.args = args; } def getSteps() = { steps; doesn’t need a block } def setSteps(steps:List[Step]) { •New line implies ; this.steps = steps; } def getName() = { name; } def setName(name:String) { this.name = name; } }
  • 52. class Job { private var name:String = null; Remove redundancy private var steps:List[Step] = null; private var args:Map[String, Object] = null; •The last statement is def getArgs() = args; returned •Types are inferred def setArgs(args:Map[String, Object]) { •No = implies Unit •Single statement this.args = args; } def getSteps() = steps; doesn’t need a block def setSteps(steps:List[Step]) { •New line implies ; this.steps = steps; } def getName() = name; def setName(name:String) { this.name = name; } }
  • 53. class Job { private var name:String = null; Remove redundancy private var steps:List[Step] = null; private var args:Map[String, Object] = null; •The last statement is def getArgs() = args; returned •Types are inferred def setArgs(args:Map[String, Object]) { •No = implies Unit •Single statement this.args = args; } def getSteps() = steps; doesn’t need a block def setSteps(steps:List[Step]) { •New line implies ; this.steps = steps; } def getName() = name; def setName(name:String) { this.name = name; } }
  • 54. class Job { private var name:String = null Remove redundancy private var steps:List[Step] = null private var args:Map[String, Object] = null •The last statement is def getArgs() = args returned •Types are inferred def setArgs(args:Map[String, Object]) { •No = implies Unit •Single statement this.args = args } def getSteps() = steps doesn’t need a block def setSteps(steps:List[Step]) { •New line implies ; this.steps = steps } def getName() = name def setName(name:String) { this.name = name } }
  • 55. class Job { private var name:String = null Remove redundancy private var steps:List[Step] = null private var args:Map[String, Object] = null •The last statement is def getArgs() = args returned •Types are inferred def setArgs(args:Map[String, Object]) { •No = implies Unit •Single statement this.args = args } def getSteps() = steps doesn’t need a block def setSteps(steps:List[Step]) { •New line implies ; this.steps = steps } def getName() = name def setName(name:String) { this.name = name } }
  • 56. class Job { private var name:String = null Redundancy private var steps:List[Step] = null private var args:Map[String, Object] = null •The last statement is def getArgs() = args returned •Types are inferred def setArgs(args:Map[String, Object]) { •No = implies Unit •Single statement this.args = args } def getSteps() = steps doesn’t need a block def setSteps(steps:List[Step]) { •New line implies ; this.steps = steps } def getName() = name def setName(name:String) { this.name = name } }
  • 57. class Job { private var name:String = null private var steps:List[Step] = null private var args:Map[String, Object] = null def getArgs() = args def setArgs(args:Map[String, Object]) { this.args = args } def getSteps() = steps There is an even shorter form! def setSteps(steps:List[Step]) { this.steps = steps } def getName() = name def setName(name:String) { this.name = name } }
  • 58. class Job { import scala.reflect._ private var name:String = null class Job { private var steps:List[Step] = null @BeanProperty private var args:Map[String, Object] = null var name:String = null @BeanProperty def getArgs() = args var steps:List[Step] = null @BeanProperty var args:Map[String, Object] = null def setArgs(args:Map[String, Object]) { } this.args = args } def getSteps() = steps def setSteps(steps:List[Step]) { this.steps = steps } def getName() = name def setName(name:String) { this.name = name } }
  • 59. public class Job { import scala.reflect._ private String name; class Job { private List<Step> steps; @BeanProperty private Map<String, Object> args; var name:String = null @BeanProperty public Map<String, Object> getArgs() { var steps:List[Step] = null return args; @BeanProperty } var args:Map[String, Object] = null public void setArgs(Map<String, Object> } args) { this.args = args; } public List<Step> getSteps() { return steps; } public void setSteps(List<Step> steps) { this.steps = steps; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
  • 60. public class Job { import scala.reflect._ private String name; class Job { private List<Step> steps; @BeanProperty private Map<String, Object> args; var name:String = null @BeanProperty public Map<String, Object> getArgs() { var steps:List[Step] = null return args; @BeanProperty } var args:Map[String, Object] = null public void setArgs(Map<String, Object> } args) { this.args = args; SCALA SMALL } public List<Step> getSteps() { return steps; } public void setSteps(List<Step> steps) { this.steps = steps; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
  • 61. public class Job { import scala.reflect._ private String name; class Job { private List<Step> steps; @BeanProperty private Map<String, Object> args; var name:String = null @BeanProperty public Map<String, Object> getArgs() { var steps:List[Step] = null return args; @BeanProperty } var args:Map[String, Object] = null public void setArgs(Map<String, Object> } More compact args) { this.args = args; } public List<Step> getSteps() { return steps; } But still a Java mindset public void setSteps(List<Step> steps) { this.steps = steps; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
  • 62. import scala.reflect._ class Job { [Make it immutable] @BeanProperty var name:String = null •Add a constructor @BeanProperty var steps:List[Step] = null •Make fields immutable @BeanProperty var args:Map[String, Object] = null •Use default arguments •Create by name }
  • 63. import scala.reflect._ class Job { [Make it immutable] @BeanProperty var name:String = null •Add a constructor @BeanProperty var steps:List[Step] = null •Make fields immutable @BeanProperty var args:Map[String, Object] = null •Use default arguments •Create by name }
  • 64. import scala.reflect._ class Job ( [Make it immutable] @BeanProperty var name:String, •Add a constructor @BeanProperty var steps:List[Step], •Make fields immutable @BeanProperty var args:Map[String, Object] •Use default arguments •Create by name ) { }
  • 65. import scala.reflect._ class Job ( [Make it immutable] @BeanProperty var name:String, •Add a constructor @BeanProperty var steps:List[Step], •Make fields immutable @BeanProperty var args:Map[String, Object] •Use default arguments •Create by name ) { }
  • 66. import scala.reflect._ class Job ( [Make it immutable] @BeanProperty val name:String, •Add a constructor @BeanProperty val steps:List[Step], •Make fields immutable @BeanProperty val args:Map[String, Object] •Use default arguments •Create by name ) { }
  • 67. import scala.reflect._ class Job ( [Make it immutable] @BeanProperty val name:String, •Add a constructor @BeanProperty val steps:List[Step], •Make fields immutable @BeanProperty val args:Map[String, Object] •Use default arguments •Create by name ) { }
  • 68. import scala.reflect._ class Job ( [Make it immutable] @BeanProperty val name:String = “no name”, •Add a constructor @BeanProperty val steps:List[Step] = emptyList, •Make fields immutable @BeanProperty val args:Map[String, Object] = •Use default emptyMap arguments •Create by name ) { }
  • 69. import scala.reflect._ class Job ( [Make it immutable] @BeanProperty val name:String = “no name”, •Add a constructor @BeanProperty val steps:List[Step] = emptyList, •Make fields immutable @BeanProperty val args:Map[String, Object] = •Use default emptyMap arguments •Create by name ) { }
  • 70. import scala.reflect._ class Job ( [Make it immutable] @BeanProperty val name:String = “no name”, •Add a constructor @BeanProperty val steps:List[Step] = emptyList, •Make fields immutable @BeanProperty val args:Map[String, Object] = •Use default emptyMap arguments •Create by name ) { } new Job ( name = “an empty job” )
  • 71. import scala.reflect._ class Job ( [Make it immutable] @BeanProperty val name:String = “no name”, •Add a constructor @BeanProperty val steps:List[Step] = emptyList, •Make fields immutable @BeanProperty val args:Map[String, Object] = •Use default emptyMap arguments •Create by name ) { } new Job ( name = “an empty job” )
  • 75. 1.1 Inn er cla sse s 1.2 str co ictfp lle cti key on wo lib rd, rar re 1.4 ass y fle er cti tk on ey wo , En rd 1.5 an ums no , g tat en ion eri s, s cs, tat 1.7 Ho ic im JAVA HAS EVOLVED or ay po !P r ts ro jec tC oin !
  • 76. 1.1 Inn er cla sse s 1.2 str co ictfp lle cti key on wo lib rd, rar re 1.4 ass y fle er cti tk on ey wo , En rd 1.5 an ums no , g tat en ion eri s, s cs, tat 1.7 Ho ic im JAVA HAS EVOLVED or ay po !P Good concepts have to be twisted to fit into Java ro r ts jec tC oin !
  • 79. Java Coooooobooool 1996 -2006
  • 81. WHY SCALA AGAIN? •Byte code compatible with Java •Designed for extendability •A higher level of abstraction
  • 82. "If I'd asked my customers what they wanted, they'd have said a faster horse." - Henry Ford
  • 84. PROJECT LAYOUT Java Scala Java Application Module Module
  • 85. PROJECT LAYOUT JobControl.scala Java Scala Java Application Module Module
  • 86. Exploit Scala public class JobControl { private JobFactory jf; Move a “logic” class public JobControl(JobFactory jf) { from Java to Scala so this.jf = jf; } that we can use Scala for more than just public void startJob(String name) { Job job = jf.create(name); beans if (job != null) { Map<String, Object> context = new HashMap<String, Object>(); for (Step step : job.getSteps()) { step.getCommand().run(context); } } } }
  • 87. Exploit Scala class JobControl(jf:JobFactory) { Same steps as before def startJob(name:String) = { val job = jf.create(name) if (job != null) { val context = new HashMap[String, Object]() for (step <- job.getSteps()) { step.getCommand().run(context) } } } }
  • 88. Exploit Scala class JobControl(jf:JobFactory) { Same steps as before Observe the for syntax def startJob(name:String) = { val job = jf.create(name) if (job != null) { val context = new HashMap[String, Object]() for (step <- job.getSteps()) { step.getCommand().run(context) } } } }
  • 89. Exploit Scala class JobControl(jf:JobFactory) { Same steps as before Observe the for syntax def startJob(name:String) = { Does not compile, val job = jf.create(name) needs the result of if (job != null) { val context = getSteps to implement new HashMap[String, Object]() a foreach-method for (step <- job.getSteps()) { step.getCommand().run(context) } } } }
  • 90. Exploit Scala class JobControl(jf:JobFactory) { Same steps as before Observe the for syntax def startJob(name:String) = { Does not compile, val job = jf.create(name) needs the result of if (job != null) { val context = getSteps to implement new HashMap[String, Object]() a foreach-method for (step <- job.getSteps()) { step.getCommand().run(context) } } Tip: Google for } } “structural typing”
  • 91. import scala.collection.JavaConversions._ Exploit Scala class JobControl(jf:JobFactory) { Scala 2.8 to the rescue: def startJob(name:String) = { val job = jf.create(name) if (job != null) { val context = new HashMap[String, Object]() for (step <- job.getSteps()) { step.getCommand().run(context) } } } }
  • 92. import scala.collection.JavaConversions._ Exploit Scala class JobControl(jf:JobFactory) { Scala 2.8 to the rescue: Implicit java conversions! def startJob(name:String) = { val job = jf.create(name) if (job != null) { val context = new HashMap[String, Object]() for (step <- job.getSteps()) { step.getCommand().run(context) } } } }
  • 93. import scala.collection.JavaConversions._ Exploit Scala class JobControl(jf:JobFactory) { Scala 2.8 to the rescue: Implicit java conversions! def startJob(name:String) = { val job = jf.create(name) if (job != null) { val context = new HashMap[String, Object]() for (step <- job.getSteps()) { step.getCommand().run(context) } } } }
  • 94. import scala.collection.JavaConversions._ Exploit Scala class JobControl(jf:JobFactory) { Scala 2.8 to the rescue: Implicit java conversions! def startJob(name:String) = { SCALA ☠ NULL val job = jf.create(name) if (job != null) { val context = new HashMap[String, Object]() for (step <- job.getSteps()) { step.getCommand().run(context) } } } }
  • 95. import scala.collection.JavaConversions._ Exploit Scala class JobControl(jf:JobFactory) { Scala 2.8 to the rescue: Implicit java conversions! def startJob(name:String) = { SCALA val job = jf.create(name) if (job != null) { val context = OPTIONS new HashMap[String, Object]() for (step <- job.getSteps()) { step.getCommand().run(context) } } } }
  • 96. import scala.collection.JavaConversions._ Exploit Scala class JobControl(jf:JobFactory) { Scala 2.8 to the rescue: Implicit java conversions! def startJob(name:String) = { val job = jf.create(name) if (job != null) { val context = new HashMap[String, Object]() for (step <- job.getSteps()) { step.getCommand().run(context) } } } }
  • 97. trait JobFactory { def create(name:String):Job Exploit Scala Scala’s equivalent of interfaces: Traits }
  • 98. trait JobFactory { def create(name:String):Job Exploit Scala def apply(name:String):Option[Job] Create an alternative method that optionally returns a Job As we will see, the name “apply” has a } special meaning in Scala
  • 99. trait JobFactory { def create(name:String):Job Exploit Scala def apply(name:String):Option[Job] = { Traits can have val job = create(name) if (job == null) { implementations None } else { Mix ins: “Compiler copy Some(job) } + paste :)” } }
  • 100. trait JobFactory { def create(name:String):Job Exploit Scala def apply(name:String):Option[Job] = { Traits can have val job = create(name) if (job == null) { implementations None } else { Mix ins: “Compiler copy Some(job) } + paste :)” } } Everything has a value in Scala!
  • 101. trait JobFactory { def create(name:String):Job Exploit Scala def apply(name:String):Option[Job] = { Java will only see the val job = create(name) if (job == null) { interface so we need } None an adapter. else { Some(job) } An abstract base-class? } } abstract class AbstractJobFactory extends Object with JobFactory
  • 102. trait JobFactory { def create(name:String):Job Exploit Scala def apply(name:String):Option[Job] = { Pattern-matching is val job = create(name) job match { more compact, more case null => None “scala” and can give you more compiler case job => Some(job) } support. } } NOT THE SAME AS abstract class AbstractJobFactory extends Object with JobFactory SWITCH CASE IN JAVA!!!
  • 103. import scala.collection.JavaConversions._ Exploit Scala class JobControl(jf:JobFactory) { Time to use our def startJob(name:String) = { val job = jf.create(name) “improved” factory if (job != null) { val context = new HashMap[String, Object]() for (step <- job.getSteps()) { step.getCommand().run(context) } } } }
  • 104. import scala.collection.JavaConversions._ Exploit Scala class JobControl(jf:JobFactory) { The option “enforces” def startJob(name:String) = { val job = jf.apply(name). handling the None- getOrElse(EMPTY_JOB) case. You can’t get the value unless you val context = new HashMap[String, Object]() provide what to return for (step <- job.getSteps()) { if the option is empty step.getCommand().run(context) } (None) } }
  • 105. import scala.collection.JavaConversions._ Exploit Scala class JobControl(jf:JobFactory) { The option “enforces” def startJob(name:String) = { val job = jf.apply(name). handling the None- getOrElse(EMPTY_JOB) case. You can’t get the value unless you val context = new HashMap[String, Object]() provide what to return for (step <- job.getSteps()) { if the option is empty step.getCommand().run(context) } (None) } }
  • 106. import scala.collection.JavaConversions._ Exploit Scala class JobControl(jf:JobFactory) { Told you the apply def startJob(name:String) = { val job = jf(name). name was special! getOrElse(EMPTY_JOB) val context = new HashMap[String, Object]() for (step <- job.getSteps()) { step.getCommand().run(context) } } }
  • 107. import scala.collection.JavaConversions._ Exploit Scala class JobControl(jf:JobFactory) { We can also execute def startJob(name:String) = { val job = jf(name). code if the option is getOrElse( {println(“hello”) empty error("No job with name: "+name)}) val context = new HashMap[String, Object]() for (step <- job.getSteps()) { step.getCommand().run(context) } } }
  • 108. import scala.collection.JavaConversions._ Exploit Scala class JobControl(jf:JobFactory) { We can also execute def startJob(name:String) = { val job = jf(name). code if the option is getOrElse( {println(“hello”) empty error("No job with name: "+name)}) val context = new HashMap[String, Object]() SCALA for (step <- job.getSteps()) { FUNCTIONS step.getCommand().run(context) } } }
  • 109. SCALA FUNCTIONS
  • 110. SCALA FUNCTIONS
  • 111. SCALA FUNCTIONS AC DC
  • 112. SCALA FUNCTIONS AC DC
  • 113. SCALA FUNCTIONS AC DC
  • 114. SCALA FUNCTIONS ( AC ) => DC
  • 115. SCALA FUNCTIONS Type val transformer: ( AC ) => DC
  • 116. SCALA FUNCTIONS ( AC ) => DC
  • 117. SCALA FUNCTIONS ( String ) => Option[Job]
  • 118. SCALA FUNCTIONS ( String ) => Option[Job] Function[String, Option[Job]]
  • 119. import scala.collection.JavaConversions._ Exploit Scala class JobControl(jf:JobFactory) { We can also execute def startJob(name:String) = { val job = jf(name). code if the option is getOrElse( {println(“hello”) empty error("No job with name: "+name)}) val context = new HashMap[String, Object]() SCALA for (step <- job.getSteps()) { FUNCTIONS step.getCommand().run(context) } } }
  • 120. import scala.collection.JavaConversions._ Exploit Scala class JobControl(jf:JobFactory) { We can also execute def startJob(name:String) = { val job = jf(name). code if the option is getOrElse( {println(“hello”) empty error("No job with name: "+name)}) val context = new HashMap[String, Object]() for (step <- job.getSteps()) { step.getCommand().run(context) } } }
  • 121. trait JobFactory { Use functions Functions as Factories def create(name:String):Job def apply(name:String):Option[Job] = { Factories as Functions create(name) match { case null => None case job => Some(job) } } } abstract class AbstractJobFactory extends Object with JobFactory
  • 122. trait JobFactory extends Function[String, Option[Job]] { Use functions def create(name:String):Job def apply(name:String):Option[Job] = { Functions are objects create(name) match { and can be extended case null => None case job => Some(job) } We already implement } } apply abstract class AbstractJobFactory extends Object with JobFactory
  • 123. import scala.collection.JavaConversions._ Use functions class JobControl(jf:JobFactory) { def startJob(name:String) = { val job = jf(name). We can now change val context = getOrElse(EMPTY_JOB) our dependencies from new HashMap[String, Object]() JobControl... for (step <- job.getSteps()) { step.getCommand().run(context) } } }
  • 124. import scala.collection.JavaConversions._ Use functions class JobControl(jf:JobFactory) { def startJob(name:String) = { val job = jf(name). We can now change val context = getOrElse(EMPTY_JOB) our dependencies from new HashMap[String, Object]() JobControl... for (step <- job.getSteps()) { step.getCommand().run(context) } } }
  • 125. import scala.collection.JavaConversions._ Use functions class JobControl(jf:(String)=>Option[Job]) { def startJob(name:String) = { val job = jf(name). Let’s depend on a val context = getOrElse(EMPTY_JOB) function instead of a new HashMap[String, Object]() factory for (step <- job.getSteps()) { step.getCommand().run(context) } } }
  • 126. FUNCTIONS AS FACTORIES def emptyJobFactory(name:String) = { Some(new Job(name, emptyJavaList, emptyJavaMap)) } new JobControl(emptyJobFactory)
  • 127. PROJECT LAYOUT Java Scala Java Application Module Module
  • 128. PROJECT LAYOUT Main.java Java Scala Java Application Module Module
  • 129. STILL A FACTORY IN JAVA! Defined in Java public static void main(String[] args) { Defined in Scala JobFactory factory = new JdbcJobFactory(); JobControl control = new JobControl(factory); ... }
  • 130. STILL A FACTORY IN JAVA! public static void main(String[] args) { JobFactory factory = new JdbcJobFactory(); SCALA JAVA JobControl control = new JobControl(factory); ... }
  • 131. STILL A FACTORY IN JAVA! public static void main(String[] args) { JobFactory factory = new JdbcJobFactory(); JobControl control = new JobControl(factory); ... }
  • 132. IN CONCLUSION You don’t have to use everything Scala has to offer right away! You don’t even have to understand ALL the concepts of Scala to start coding Scala
  • 133. IN CONCLUSION It’s EASY to start programming Scala... It’s HARD to stop!
  • 134. YOU HAVE BEEN WATCHING
  • 135. YOU HAVE BEEN WATCHING Enno Runne email: enno@runne.net hlr ogge gical.com im O ogge@a Joak .ohlr joa kim ogge press.com ohlr ord : @j itter lrogge.w tw http://a ttp:/ /joh gical.co h http://a m/reso gical.co urces/a http://a m/reso r ticles/ gical.co urces/a s4jp.pd m/reso r ticles/ f urces/a s4jp.m r ticles/ ov s4jp.ke y