SlideShare a Scribd company logo
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
Ad

More Related Content

What's hot (20)

Scala introduction
Scala introductionScala introduction
Scala introduction
Yardena Meymann
 
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
Derek Chen-Becker
 
All about scala
All about scalaAll about scala
All about scala
Yardena Meymann
 
Functional Objects & Function and Closures
Functional Objects  & Function and ClosuresFunctional Objects  & Function and Closures
Functional Objects & Function and Closures
Sandip 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
 
Scala - brief intro
Scala - brief introScala - brief intro
Scala - brief intro
Razvan Cojocaru
 
camel-scala.pdf
camel-scala.pdfcamel-scala.pdf
camel-scala.pdf
Hiroshi Ono
 
Scale up your thinking
Scale up your thinkingScale up your thinking
Scale up your thinking
Yardena Meymann
 
Solid and Sustainable Development in Scala
Solid and Sustainable Development in ScalaSolid and Sustainable Development in Scala
Solid and Sustainable Development in Scala
scalaconfjp
 
Scala Reflection & Runtime MetaProgramming
Scala Reflection & Runtime MetaProgrammingScala Reflection & Runtime MetaProgramming
Scala Reflection & Runtime MetaProgramming
Meir 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 Developers
Miles Sabin
 
Java 7 New Features
Java 7 New FeaturesJava 7 New Features
Java 7 New Features
Jussi Pohjolainen
 
Scala presentationjune112011
Scala presentationjune112011Scala presentationjune112011
Scala presentationjune112011
PrasannaKumar Sathyanarayanan
 
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
 
Java 5 and 6 New Features
Java 5 and 6 New FeaturesJava 5 and 6 New Features
Java 5 and 6 New Features
Jussi Pohjolainen
 
Functional java 8
Functional java 8Functional java 8
Functional java 8
nick_maiorano
 
Scala for scripting
Scala for scriptingScala for scripting
Scala for scripting
michid
 
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
Isaias Barroso
 
An Introduction to Scala
An Introduction to ScalaAn Introduction to Scala
An Introduction to Scala
Brent Lemons
 
Java scriptforjavadev part2a
Java scriptforjavadev part2aJava scriptforjavadev part2a
Java scriptforjavadev part2a
Makarand Bhatambarekar
 
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
Derek Chen-Becker
 
Functional Objects & Function and Closures
Functional Objects  & Function and ClosuresFunctional Objects  & Function and Closures
Functional Objects & Function and Closures
Sandip 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 Scala
scalaconfjp
 
Scala Reflection & Runtime MetaProgramming
Scala Reflection & Runtime MetaProgrammingScala Reflection & Runtime MetaProgramming
Scala Reflection & Runtime MetaProgramming
Meir 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 Developers
Miles 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 scripting
michid
 
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
Isaias Barroso
 
An Introduction to Scala
An Introduction to ScalaAn Introduction to Scala
An Introduction to Scala
Brent Lemons
 

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
Riccardo 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 Programming
Riccardo 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 MVVM
Riccardo Cardin
 
A (too) Short Introduction to Scala
A (too) Short Introduction to ScalaA (too) Short Introduction to Scala
A (too) Short Introduction to Scala
Riccardo Cardin
 
Java - Processing input and output
Java - Processing input and outputJava - Processing input and output
Java - Processing input and output
Riccardo Cardin
 
Design Pattern Strutturali
Design Pattern StrutturaliDesign Pattern Strutturali
Design Pattern Strutturali
Riccardo Cardin
 
Java Exception Handling, Assertions and Logging
Java Exception Handling, Assertions and LoggingJava Exception Handling, Assertions and Logging
Java Exception Handling, Assertions and Logging
Riccardo 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 concepts
Riccardo Cardin
 
Java - Remote method invocation
Java - Remote method invocationJava - Remote method invocation
Java - Remote method invocation
Riccardo Cardin
 
Software architecture patterns
Software architecture patternsSoftware architecture patterns
Software architecture patterns
Riccardo Cardin
 
Java - Sockets
Java - SocketsJava - Sockets
Java - Sockets
Riccardo Cardin
 
Diagrammi delle Classi
Diagrammi delle ClassiDiagrammi delle Classi
Diagrammi delle Classi
Riccardo Cardin
 
Introduzione ai Design Pattern
Introduzione ai Design PatternIntroduzione ai Design Pattern
Introduzione ai Design Pattern
Riccardo Cardin
 
Presto updates to 0.178
Presto updates to 0.178Presto updates to 0.178
Presto updates to 0.178
Kai 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 Requisiti
Riccardo Cardin
 
Java - Concurrent programming - Thread's basics
Java - Concurrent programming - Thread's basicsJava - Concurrent programming - Thread's basics
Java - Concurrent programming - Thread's basics
Riccardo Cardin
 
Diagrammi di Sequenza
Diagrammi di SequenzaDiagrammi di Sequenza
Diagrammi di Sequenza
Riccardo 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 ugly
Bozhidar Bozhanov
 
SOLID - Principles of Object Oriented Design
SOLID - Principles of Object Oriented DesignSOLID - Principles of Object Oriented Design
SOLID - Principles of Object Oriented Design
Riccardo 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 Programming
Riccardo 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 MVVM
Riccardo Cardin
 
A (too) Short Introduction to Scala
A (too) Short Introduction to ScalaA (too) Short Introduction to Scala
A (too) Short Introduction to Scala
Riccardo Cardin
 
Java - Processing input and output
Java - Processing input and outputJava - Processing input and output
Java - Processing input and output
Riccardo Cardin
 
Design Pattern Strutturali
Design Pattern StrutturaliDesign Pattern Strutturali
Design Pattern Strutturali
Riccardo Cardin
 
Java Exception Handling, Assertions and Logging
Java Exception Handling, Assertions and LoggingJava Exception Handling, Assertions and Logging
Java Exception Handling, Assertions and Logging
Riccardo 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 concepts
Riccardo Cardin
 
Java - Remote method invocation
Java - Remote method invocationJava - Remote method invocation
Java - Remote method invocation
Riccardo Cardin
 
Software architecture patterns
Software architecture patternsSoftware architecture patterns
Software architecture patterns
Riccardo Cardin
 
Introduzione ai Design Pattern
Introduzione ai Design PatternIntroduzione ai Design Pattern
Introduzione ai Design Pattern
Riccardo Cardin
 
Presto updates to 0.178
Presto updates to 0.178Presto updates to 0.178
Presto updates to 0.178
Kai 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 Requisiti
Riccardo Cardin
 
Java - Concurrent programming - Thread's basics
Java - Concurrent programming - Thread's basicsJava - Concurrent programming - Thread's basics
Java - Concurrent programming - Thread's basics
Riccardo 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 ugly
Bozhidar Bozhanov
 
Ad

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
Mite Mitreski
 
Beyond java8
Beyond java8Beyond java8
Beyond java8
Muhammad Durrah
 
Alternate JVM Languages
Alternate JVM LanguagesAlternate JVM Languages
Alternate JVM Languages
Saltmarch Media
 
JS OO and Closures
JS OO and ClosuresJS OO and Closures
JS OO and Closures
Jussi Pohjolainen
 
Building Smart Async Functions For Mobile
Building Smart Async Functions For MobileBuilding Smart Async Functions For Mobile
Building Smart Async Functions For Mobile
Glan Thomas
 
Presentatie - Introductie in Groovy
Presentatie - Introductie in GroovyPresentatie - Introductie in Groovy
Presentatie - Introductie in Groovy
Getting value from IoT, Integration and Data Analytics
 
1.2 scala basics
1.2 scala basics1.2 scala basics
1.2 scala basics
wpgreenway
 
1.2 scala basics
1.2 scala basics1.2 scala basics
1.2 scala basics
futurespective
 
2.1 recap from-day_one
2.1 recap from-day_one2.1 recap from-day_one
2.1 recap from-day_one
futurespective
 
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
Codecamp Romania
 
Scala - en bedre Java?
Scala - en bedre Java?Scala - en bedre Java?
Scala - en bedre Java?
Jesper Kamstrup Linnet
 
Type script, for dummies
Type script, for dummiesType script, for dummies
Type script, for dummies
santiagoaguiar
 
LinkedIn TBC JavaScript 100: Functions
 LinkedIn TBC JavaScript 100: Functions LinkedIn TBC JavaScript 100: Functions
LinkedIn TBC JavaScript 100: Functions
Adam 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 3
Kirill Rozov
 
Pattern Matching in Java 14
Pattern Matching in Java 14Pattern Matching in Java 14
Pattern Matching in Java 14
GlobalLogic Ukraine
 
Scala in practice
Scala in practiceScala in practice
Scala in practice
andyrobinson8
 
25-functions.ppt
25-functions.ppt25-functions.ppt
25-functions.ppt
JyothiAmpally
 
ArrayOperations.java import java.util.Arrays; import java.util.pdf
ArrayOperations.java import java.util.Arrays; import java.util.pdfArrayOperations.java import java.util.Arrays; import java.util.pdf
ArrayOperations.java import java.util.Arrays; import java.util.pdf
ANANDSALESINDIA105
 
Intro to scala
Intro to scalaIntro to scala
Intro to scala
Joe Zulli
 
Google Guava for cleaner code
Google Guava for cleaner codeGoogle Guava for cleaner code
Google Guava for cleaner code
Mite Mitreski
 
Building Smart Async Functions For Mobile
Building Smart Async Functions For MobileBuilding Smart Async Functions For Mobile
Building Smart Async Functions For Mobile
Glan Thomas
 
1.2 scala basics
1.2 scala basics1.2 scala basics
1.2 scala basics
wpgreenway
 
2.1 recap from-day_one
2.1 recap from-day_one2.1 recap from-day_one
2.1 recap from-day_one
futurespective
 
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
Codecamp Romania
 
Type script, for dummies
Type script, for dummiesType script, for dummies
Type script, for dummies
santiagoaguiar
 
LinkedIn TBC JavaScript 100: Functions
 LinkedIn TBC JavaScript 100: Functions LinkedIn TBC JavaScript 100: Functions
LinkedIn TBC JavaScript 100: Functions
Adam 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 3
Kirill Rozov
 
ArrayOperations.java import java.util.Arrays; import java.util.pdf
ArrayOperations.java import java.util.Arrays; import java.util.pdfArrayOperations.java import java.util.Arrays; import java.util.pdf
ArrayOperations.java import java.util.Arrays; import java.util.pdf
ANANDSALESINDIA105
 
Intro to scala
Intro to scalaIntro to scala
Intro to scala
Joe Zulli
 
Ad

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
Enno 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 2019
Enno Runne
 
Always on. 2018-10 Reactive Summit
Always on. 2018-10 Reactive SummitAlways on. 2018-10 Reactive Summit
Always on. 2018-10 Reactive Summit
Enno Runne
 
Webinar Alpakka 2018-08-16
Webinar Alpakka 2018-08-16Webinar Alpakka 2018-08-16
Webinar Alpakka 2018-08-16
Enno Runne
 
Programming in pain
Programming in painProgramming in pain
Programming in pain
Enno Runne
 
Real generics
Real genericsReal generics
Real generics
Enno Runne
 
Let the alpakka pull your stream
Let the alpakka pull your streamLet the alpakka pull your stream
Let the alpakka pull your stream
Enno 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 2019
Enno Runne
 
Always on. 2018-10 Reactive Summit
Always on. 2018-10 Reactive SummitAlways on. 2018-10 Reactive Summit
Always on. 2018-10 Reactive Summit
Enno Runne
 
Webinar Alpakka 2018-08-16
Webinar Alpakka 2018-08-16Webinar Alpakka 2018-08-16
Webinar Alpakka 2018-08-16
Enno Runne
 
Programming in pain
Programming in painProgramming in pain
Programming in pain
Enno Runne
 

Recently uploaded (20)

Kit-Works Team Study_아직도 Dockefile.pdf_김성호
Kit-Works Team Study_아직도 Dockefile.pdf_김성호Kit-Works Team Study_아직도 Dockefile.pdf_김성호
Kit-Works Team Study_아직도 Dockefile.pdf_김성호
Wonjun Hwang
 
Does Pornify Allow NSFW? Everything You Should Know
Does Pornify Allow NSFW? Everything You Should KnowDoes Pornify Allow NSFW? Everything You Should Know
Does Pornify Allow NSFW? Everything You Should Know
Pornify CC
 
Hybridize Functions: A Tool for Automatically Refactoring Imperative Deep Lea...
Hybridize Functions: A Tool for Automatically Refactoring Imperative Deep Lea...Hybridize Functions: A Tool for Automatically Refactoring Imperative Deep Lea...
Hybridize Functions: A Tool for Automatically Refactoring Imperative Deep Lea...
Raffi Khatchadourian
 
Financial Services Technology Summit 2025
Financial Services Technology Summit 2025Financial Services Technology Summit 2025
Financial Services Technology Summit 2025
Ray Bugg
 
UiPath Agentic Automation: Community Developer Opportunities
UiPath Agentic Automation: Community Developer OpportunitiesUiPath Agentic Automation: Community Developer Opportunities
UiPath Agentic Automation: Community Developer Opportunities
DianaGray10
 
GDG Cloud Southlake #42: Suresh Mathew: Autonomous Resource Optimization: How...
GDG Cloud Southlake #42: Suresh Mathew: Autonomous Resource Optimization: How...GDG Cloud Southlake #42: Suresh Mathew: Autonomous Resource Optimization: How...
GDG Cloud Southlake #42: Suresh Mathew: Autonomous Resource Optimization: How...
James Anderson
 
AI You Can Trust: The Critical Role of Governance and Quality.pdf
AI You Can Trust: The Critical Role of Governance and Quality.pdfAI You Can Trust: The Critical Role of Governance and Quality.pdf
AI You Can Trust: The Critical Role of Governance and Quality.pdf
Precisely
 
Webinar - Top 5 Backup Mistakes MSPs and Businesses Make .pptx
Webinar - Top 5 Backup Mistakes MSPs and Businesses Make   .pptxWebinar - Top 5 Backup Mistakes MSPs and Businesses Make   .pptx
Webinar - Top 5 Backup Mistakes MSPs and Businesses Make .pptx
MSP360
 
Viam product demo_ Deploying and scaling AI with hardware.pdf
Viam product demo_ Deploying and scaling AI with hardware.pdfViam product demo_ Deploying and scaling AI with hardware.pdf
Viam product demo_ Deploying and scaling AI with hardware.pdf
camilalamoratta
 
Integrating FME with Python: Tips, Demos, and Best Practices for Powerful Aut...
Integrating FME with Python: Tips, Demos, and Best Practices for Powerful Aut...Integrating FME with Python: Tips, Demos, and Best Practices for Powerful Aut...
Integrating FME with Python: Tips, Demos, and Best Practices for Powerful Aut...
Safe Software
 
AsyncAPI v3 : Streamlining Event-Driven API Design
AsyncAPI v3 : Streamlining Event-Driven API DesignAsyncAPI v3 : Streamlining Event-Driven API Design
AsyncAPI v3 : Streamlining Event-Driven API Design
leonid54
 
Kit-Works Team Study_팀스터디_김한솔_nuqs_20250509.pdf
Kit-Works Team Study_팀스터디_김한솔_nuqs_20250509.pdfKit-Works Team Study_팀스터디_김한솔_nuqs_20250509.pdf
Kit-Works Team Study_팀스터디_김한솔_nuqs_20250509.pdf
Wonjun Hwang
 
IT484 Cyber Forensics_Information Technology
IT484 Cyber Forensics_Information TechnologyIT484 Cyber Forensics_Information Technology
IT484 Cyber Forensics_Information Technology
SHEHABALYAMANI
 
Config 2025 presentation recap covering both days
Config 2025 presentation recap covering both daysConfig 2025 presentation recap covering both days
Config 2025 presentation recap covering both days
TrishAntoni1
 
AI x Accessibility UXPA by Stew Smith and Olivier Vroom
AI x Accessibility UXPA by Stew Smith and Olivier VroomAI x Accessibility UXPA by Stew Smith and Olivier Vroom
AI x Accessibility UXPA by Stew Smith and Olivier Vroom
UXPA Boston
 
Build With AI - In Person Session Slides.pdf
Build With AI - In Person Session Slides.pdfBuild With AI - In Person Session Slides.pdf
Build With AI - In Person Session Slides.pdf
Google Developer Group - Harare
 
UiPath Agentic Automation: Community Developer Opportunities
UiPath Agentic Automation: Community Developer OpportunitiesUiPath Agentic Automation: Community Developer Opportunities
UiPath Agentic Automation: Community Developer Opportunities
DianaGray10
 
Cybersecurity Threat Vectors and Mitigation
Cybersecurity Threat Vectors and MitigationCybersecurity Threat Vectors and Mitigation
Cybersecurity Threat Vectors and Mitigation
VICTOR MAESTRE RAMIREZ
 
fennec fox optimization algorithm for optimal solution
fennec fox optimization algorithm for optimal solutionfennec fox optimization algorithm for optimal solution
fennec fox optimization algorithm for optimal solution
shallal2
 
AI 3-in-1: Agents, RAG, and Local Models - Brent Laster
AI 3-in-1: Agents, RAG, and Local Models - Brent LasterAI 3-in-1: Agents, RAG, and Local Models - Brent Laster
AI 3-in-1: Agents, RAG, and Local Models - Brent Laster
All Things Open
 
Kit-Works Team Study_아직도 Dockefile.pdf_김성호
Kit-Works Team Study_아직도 Dockefile.pdf_김성호Kit-Works Team Study_아직도 Dockefile.pdf_김성호
Kit-Works Team Study_아직도 Dockefile.pdf_김성호
Wonjun Hwang
 
Does Pornify Allow NSFW? Everything You Should Know
Does Pornify Allow NSFW? Everything You Should KnowDoes Pornify Allow NSFW? Everything You Should Know
Does Pornify Allow NSFW? Everything You Should Know
Pornify CC
 
Hybridize Functions: A Tool for Automatically Refactoring Imperative Deep Lea...
Hybridize Functions: A Tool for Automatically Refactoring Imperative Deep Lea...Hybridize Functions: A Tool for Automatically Refactoring Imperative Deep Lea...
Hybridize Functions: A Tool for Automatically Refactoring Imperative Deep Lea...
Raffi Khatchadourian
 
Financial Services Technology Summit 2025
Financial Services Technology Summit 2025Financial Services Technology Summit 2025
Financial Services Technology Summit 2025
Ray Bugg
 
UiPath Agentic Automation: Community Developer Opportunities
UiPath Agentic Automation: Community Developer OpportunitiesUiPath Agentic Automation: Community Developer Opportunities
UiPath Agentic Automation: Community Developer Opportunities
DianaGray10
 
GDG Cloud Southlake #42: Suresh Mathew: Autonomous Resource Optimization: How...
GDG Cloud Southlake #42: Suresh Mathew: Autonomous Resource Optimization: How...GDG Cloud Southlake #42: Suresh Mathew: Autonomous Resource Optimization: How...
GDG Cloud Southlake #42: Suresh Mathew: Autonomous Resource Optimization: How...
James Anderson
 
AI You Can Trust: The Critical Role of Governance and Quality.pdf
AI You Can Trust: The Critical Role of Governance and Quality.pdfAI You Can Trust: The Critical Role of Governance and Quality.pdf
AI You Can Trust: The Critical Role of Governance and Quality.pdf
Precisely
 
Webinar - Top 5 Backup Mistakes MSPs and Businesses Make .pptx
Webinar - Top 5 Backup Mistakes MSPs and Businesses Make   .pptxWebinar - Top 5 Backup Mistakes MSPs and Businesses Make   .pptx
Webinar - Top 5 Backup Mistakes MSPs and Businesses Make .pptx
MSP360
 
Viam product demo_ Deploying and scaling AI with hardware.pdf
Viam product demo_ Deploying and scaling AI with hardware.pdfViam product demo_ Deploying and scaling AI with hardware.pdf
Viam product demo_ Deploying and scaling AI with hardware.pdf
camilalamoratta
 
Integrating FME with Python: Tips, Demos, and Best Practices for Powerful Aut...
Integrating FME with Python: Tips, Demos, and Best Practices for Powerful Aut...Integrating FME with Python: Tips, Demos, and Best Practices for Powerful Aut...
Integrating FME with Python: Tips, Demos, and Best Practices for Powerful Aut...
Safe Software
 
AsyncAPI v3 : Streamlining Event-Driven API Design
AsyncAPI v3 : Streamlining Event-Driven API DesignAsyncAPI v3 : Streamlining Event-Driven API Design
AsyncAPI v3 : Streamlining Event-Driven API Design
leonid54
 
Kit-Works Team Study_팀스터디_김한솔_nuqs_20250509.pdf
Kit-Works Team Study_팀스터디_김한솔_nuqs_20250509.pdfKit-Works Team Study_팀스터디_김한솔_nuqs_20250509.pdf
Kit-Works Team Study_팀스터디_김한솔_nuqs_20250509.pdf
Wonjun Hwang
 
IT484 Cyber Forensics_Information Technology
IT484 Cyber Forensics_Information TechnologyIT484 Cyber Forensics_Information Technology
IT484 Cyber Forensics_Information Technology
SHEHABALYAMANI
 
Config 2025 presentation recap covering both days
Config 2025 presentation recap covering both daysConfig 2025 presentation recap covering both days
Config 2025 presentation recap covering both days
TrishAntoni1
 
AI x Accessibility UXPA by Stew Smith and Olivier Vroom
AI x Accessibility UXPA by Stew Smith and Olivier VroomAI x Accessibility UXPA by Stew Smith and Olivier Vroom
AI x Accessibility UXPA by Stew Smith and Olivier Vroom
UXPA Boston
 
UiPath Agentic Automation: Community Developer Opportunities
UiPath Agentic Automation: Community Developer OpportunitiesUiPath Agentic Automation: Community Developer Opportunities
UiPath Agentic Automation: Community Developer Opportunities
DianaGray10
 
Cybersecurity Threat Vectors and Mitigation
Cybersecurity Threat Vectors and MitigationCybersecurity Threat Vectors and Mitigation
Cybersecurity Threat Vectors and Mitigation
VICTOR MAESTRE RAMIREZ
 
fennec fox optimization algorithm for optimal solution
fennec fox optimization algorithm for optimal solutionfennec fox optimization algorithm for optimal solution
fennec fox optimization algorithm for optimal solution
shallal2
 
AI 3-in-1: Agents, RAG, and Local Models - Brent Laster
AI 3-in-1: Agents, RAG, and Local Models - Brent LasterAI 3-in-1: Agents, RAG, and Local Models - Brent Laster
AI 3-in-1: Agents, RAG, and Local Models - Brent Laster
All Things Open
 

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
  翻译: