Scala メモ

Last Updated : 2009/5/31 (2006/7/4 より執筆開始)
asato <asatohan at gmail.com>
内容に関するコメント(感想、提案、書き間違いの指摘)は歓迎します。

概要

Scala言語のコード例を紹介。

実験環境

例 - 基本 - 1

object Main {

    def main(args: Array[String]) {
            Console.println("Hello")
    }   
}
実行結果:
Hello
Consoleは省略できます。
object Main {

    def main(args: Array[String]) {
            println("Hello")
    }   
}

例 - 基本 - 2

object Main extends Application {
    println("Hello")
}
実行結果:
Hello

例 - クラス - 1

class Person(personName : String) {

    var name : String = personName

    def getName() : String = name;
}
object Main {
        
	def main(args : Array[String]) {
		val person = new Person("aaa");
		println( person.getName() ); // aaa
	}   
}
実行結果:
aaa

例 - クラス - 2

class Person(personName : String) {

    var name : String = personName

    def setName(personName : String) {
        name = personName
    }
    
    def getName() : String = name;
}
object Main {
    
    def main(args : Array[String]) {
        
        val person = new Person("aaa");
        
        println( person.getName() ); // aaa
  
        person.setName("xxx");

        println( person.getName() ); // xxx
    }   
}
実行結果:
aaa
xxx

例 - クラス - override

class Person(personName : String) {
        
        var name : String = personName

        def getName() : String = name;
        
        override def toString(): String = "name = " + name
}
object Main {

        def main(args : Array[String]) {
                
                val person = new Person("aaa");

                println( person ) // "name = aaa"
        }   
}
実行結果:
name = aaa

例 - 抽象クラス

abstract class Shape {

    def draw
}
class Rectangle extends Shape {

    def draw = println("rectangle")   
}
class Circle extends Shape {

    def draw = println("circle")   
}
object Main extends Application {
        
    def draw(s : Shape) = s.draw   


    val s1 = new Circle
    val s2 = new Rectangle
    
    draw(s1)
    draw(s2)

}
実行結果:
circle
rectangle

例 - Trait - 1

object Main extends Application {

    trait MyTrait {
        def method {
            println("MyTrait.method")
        }
    }

    class MyClass extends MyTrait {
    
    }

    val my = new MyClass
    my.method
}
実行結果:
MyTrait.method

例 - Trait - 2

object Main extends Application {

    trait MyTrait {
        def method {
            println("MyTrait.method")
        }
    }

    class MyClass {
    }

    val my = new MyClass with MyTrait

    my.method
}
実行結果:
MyTrait.method

例 - Trait - 3

object Main extends Application {

    trait MyTraitA {

        def methodA {
            println("MyTraitA.methodA")
        }
    }

    trait MyTraitB {

        def methodB {
            println("MyTraitB.methodB")
        }
    }

    class MyClass extends MyTraitA with MyTraitB {

    }

    val my = new MyClass

     my.methodA
    my.methodB
}
実行結果:
MyTraitA.methodA
MyTraitB.methodB

例 - Trait - 4

object Main extends Application {

    trait MyTraitA {
        def methodA {
            println("MyTraitA.methodA")
        }
    }

    trait MyTraitB {
        def methodB {
            println("MyTraitB.methodB")
        }
    }

    class MyClass {

    }

    val my = new MyClass with MyTraitA with MyTraitB

    my.methodA
    my.methodB
}
実行結果:
MyTraitA.methodA
MyTraitB.methodB

例 - Trait - 5

object Main extends Application {

    class MySuperClass {
        
        def superMethod {
            println("MySuperClass.MySuperClass")
        }
    }    


    trait MyTrait {
        
        def traitMethod {
            println("MyTrait.traitMethod")
        }
    }

    class MyClass extends MySuperClass with MyTrait {
    }    
    
    val my = new MyClass
    my.superMethod
    my.traitMethod
}
実行結果:
MySuperClass.MySuperClass
MyTrait.traitMethod

例 - Trait - 6

object Main extends Application {

    abstract class MyAbstractClass {
 
       def method() {
            println("MyAbstractClass.method")
        }
    }    

    class MySuperClass extends MyAbstractClass {

        override def method() {
            println("MySuperClass.method")
        }
    }    

    trait MyTrait extends MyAbstractClass {
        
        override def method {

            println("MyTrait.method - before super.method")
            super.method
            println("MyTrait.method - after super.method")
        }
    }

    class MyClass extends MySuperClass with MyTrait {
    
    }

    val my = new MyClass
    my.method
}
実行結果:
MyTrait.method - before super.method
MySuperClass.method
MyTrait.method - after super.method
"MyAbstractClass.method" が表示されているのではないことに注意。

例 - Trait - 7

object Main extends Application {

    abstract class MyAbstractClass {
        def method();
    }    


    trait MyTrait extends MyAbstractClass {
        
        def loggedMethod {

            println("MyTraitA.method - before super.method")
            method
            println("MyTraitA.method - after super.method")
        }
    }

    class MyClass extends MyAbstractClass with MyTrait {

        def method() {
            println("MyClass.method")
        }
    }    
    
    val my = new MyClass
    my.loggedMethod

}
実行結果:
MyTraitA.method - before super.method
MyClass.method
MyTraitA.method - after super.method

例 - Trait - 8

object Main extends Application {

    abstract class MyAbstractClass {

        def method() {
            println("MyAbstractClass.method")
        }
    }    


    trait MyTraitA extends MyAbstractClass {
        
        override def method {
            println("MyTraitA.method - before super.method")
            super.method
            println("MyTraitA.method - after super.method")
        }
    }
    trait MyTraitB extends MyAbstractClass {
        
        override def method {
            println("MyTraitB.method - before super.method")
            super.method
            println("MyTraitB.method - after super.method")
        }
    }

    class MyClass extends MyAbstractClass {

    }    
    
    val myA = new MyClass with MyTraitA
    myA.method

    println()
    

    val myB = new MyClass with MyTraitB
    myB.method

    println()

    
    val myAB = new MyClass with MyTraitA with MyTraitB
    myAB.method
}
実行結果:
MyTraitA.method - before super.method
MyAbstractClass.method
MyTraitA.method - after super.method

MyTraitB.method - before super.method
MyAbstractClass.method
MyTraitB.method - after super.method

MyTraitB.method - before super.method
MyTraitA.method - before super.method
MyAbstractClass.method
MyTraitA.method - after super.method
MyTraitB.method - after super.method

例 - Case Classes - 1

object Main extends Application {

    case class MyCaseClass

    def print(c : MyCaseClass) {
        println(c)
    }
    
	print( MyCaseClass() ) // new がいらないことに注意
}
実行結果:
MyCaseClass()

例 - Case Classes - 2

object Main extends Application {

    case class MyCaseClass(s: String)

    
    val my = MyCaseClass("aaa")

    println(my.s)
}
実行結果:
aaa

例 - Case Classes - 3 - Pattern Matching

object Main extends Application {
    
    abstract class Expr

    case class Number(n: Int) extends Expr

    case class Sum(e1: Expr, e2: Expr) extends Expr


    def eval(e: Expr): Int = e match {
         case Number(x) => x
        case Sum(l, r) => eval(l) + eval(r)
    }

    val e = Sum( Number(1), Number(2) )
    val v = eval( e ) // もしくは val v = eval( Sum( Number(1), Number(2) ) )
	
    println(v) // 3
}
実行結果:
3

例 - Generic Types and Methods - 1

object Main extends Application {
    
    class Container[A] {
        def print(a: A) = println(a)
    }

    val c1 = new Container[String]
    
    c1.print("aaa")
//  c1.print(1) コンパイルエラー
    
    val c2 = new Container[Int]

//  c2.print("aaa") コンパイルエラー
    c2.print(1) 

}
実行結果:
aaa
1

例 - Generic Types and Methods - 2

object Main extends Application {
    
    abstract class MyAbstractClass {
        def print
    }
    class MyClassA extends MyAbstractClass {
        def print = println("MyClassA")
    }
    class MyClassB extends MyAbstractClass {
        def print = println("MyClassB")
    }
    
    
    class Container[My <: MyAbstractClass] {
        def print(my: My) = my.print
    }

//  val c = new Container[String] コンパイルエラー
    val c1 = new Container[MyAbstractClass]

    c1.print(new MyClassA)
    c1.print(new MyClassB)

    
    val c2 = new Container[MyClassA]

    c2.print(new MyClassA)
//  c2.print(new MyClassB) コンパイルエラー

}
実行結果:
MyClassA
MyClassB
MyClassA

例 - Generic Types and Methods - 3 - Polymorphic Methods

object Main extends Application {
    
    def print[A](a1: A, a2: A) = println(a1 + ", " + a2)

    
    print[String]("a", "b")

    print[Int](1, 2)
    
//  print[Int](1, "b") コンパイルエラー
}
実行結果:
a, b
1, 2

例 - Generic Types and Methods - 4 - variance annotations

object Main extends Application {
   
    class Cell[+T](data: T) {
      def get = data
    }

    def print(c: Cell[Any]) = println(c.get)
    
    val c = new Cell[Int](1)

    print(c)
}
実行結果:
1
a
variance annotationを使わない場合:
object Main extends Application {
   
    class Cell[T](data: T) {
      def get = data
    }

    def print(c: Cell[Any]) = println(c.get)
    
    val c = new Cell[Int](1)

    print(c) // コンパイルエラー
}

例 - Pattern Matching - 1

object Main {
    
    def main(args : Array[String]) {

        def matchTest(x: Int): String = x match {
        	
           case 1 => "one"
          case 2 => "two"
          case _ => "many"
        }        
				
        println( matchTest(1) ) // one

        println( matchTest(2) ) // two
        
        println( matchTest(3) ) // many
        
        println( matchTest(4) ) // many
    }   
}
実行結果:
one
two
many
many
関数を使わずに直接的に:
object Main extends Application {
    
    val n = 1
    
    n match {
        case 1 => println("one")
        case 2 => println("two")
        case _ => println("many")
    }
}
実行結果:
one

例 - Pattern Matching - 2

object Main extends Application {

    class MyClassA {

        def methodA() {
            println("MyClassA.methodA()")
        }
    }
    class MyClassB {

        def methodB() {
            println("MyClassB.methodB()")
        }
    }
    
    
    def matchTest(my: AnyRef) = my match {

         case a: MyClassA => a.methodA
        case b: MyClassB => b.methodB
    }
    
    val my1 = new MyClassA
    val my2 = new MyClassB
    
    matchTest(my1)
    matchTest(my2)
}
実行結果:
MyClassA.methodA()
MyClassB.methodB()

例 - Pattern Matching - 3 - case class

object Main extends Application {

    case class MyClass(var name: String)
    
    
    def matchTest(my: AnyRef) = my match {

        case MyClass(name) => println(name)
    }
    
    val my = new MyClass("aaa")

    matchTest(my)
}

実行結果:
aaa

例 - Pattern Matching - 4 - unapply

object Main extends Application {
  
    class MyClass(val _s: String)
    {
         def unapply(s: String): Option[String] =  {

            println("unapply: " + s)

            if (_s == s) Some(_s + _s) else None
        }
    }
    
    
    def matchTest(s: String, my: MyClass) = s match {

        case my(x) => println("match true: " + x)
        case _     => println("match false: " + s)
    }
    
    val my = new MyClass("a");

    matchTest("a", my)
    matchTest("b", my)
}
実行結果:
unapply: a
match true: aa
unapply: b
match false: b

例 - Pattern Matching - 5

object Main extends Application {
  
  1 match {
    case n@1 => println("n=" + n)
  }
}
実行結果:
n=1

例 - Pattern Matching - 6

object Main extends Application {
    
  1 match {
    case x => println("x=" + x)
  }
}
実行結果:
x=1

例 - Pattern Matching - 7

object Main extends Application {

  def m(x: Int, y: Int) = {

    x match {
      case `y` => println("x == y: " + x + " == " + y)
      case _   => println("x != y: " + x + " != " + y)
    }
  }
  
  m(1, 1) // "x == y: 1 == 1"
  m(1, 2) // "x != y: 1 != 2"
}
実行結果:
x == y: 1 == 1
x != y: 1 != 2

例 - Pattern Matching - 8 - pattern guards

object Main extends Application {
  
  def testMatch(o: Any) = {

    o match {
      case n: Int    if n == 1   => println("n==1")
      case s: String if s == "a" => println("s==a")
      case _                       => println("_")
    }
  }
  
  testMatch(1)   // "n==1"
  testMatch(2)   // "_"
  testMatch("a") // "s==a"
  testMatch("b") // "_"
}
実行結果:
n==1
_
s==a
_

例 - Method Values - 1

object Main extends Application {

    class StringPrinter {
        def print(s: String) = println(s)
    }

    val printer = new StringPrinter
    
    val print = printer.print _
    
    print("aaa")
}
実行結果:
aaa

例 - Higher-Order Functions - 1

object Main extends Application {
    
    def decorate(s: String): String =  { // String => String
    	"***" + s + "***" 
    }
    
    def print(s: String, f: String => String) {

        println( f(s) )
    }
    
    print("aaa", decorate) // ***aaa***
    print("bbb", decorate) // ***bbb***
}

実行結果:
***aaa***
***bbb***
例:
object Main extends Application {

    def decorate1(s: String) : String = {
        "[[[" + s + "]]]";
    }

    def decorate2(s: String) : String = {
        "***" + s + "***";
    }
    
    def print(s: String, f: String => String) {
        println( f(s) );
    }
    
    print("aaa", decorate1); // [[[aaa]]]
    print("aaa", decorate2); // ***aaa***
}
実行結果:
[[[aaa]]]
***aaa***

例 - Higher-Order Functions - 2

object Main extends Application {
    

    def decorated(d: String): String => String = {

        def decorate(s: String): String = {
            d + s + d
        }
        
        decorate
    }
    
    val f = decorated("***")
    
    println( f("aaa") )
    println( f("bbb") )
}
実行結果:
***aaa***
***bbb***

例 - Anonymous Function Syntax - 1

object Main extends Application {
        
        val f = () => println("Hello")
        
        f()
}
実行結果:
Hello

例 - Anonymous Function Syntax - 2

object Main extends Application {
        
        val f1 = (x : int) => println(x)

        val f2 = (x : int, y : int) => println(x + ", " + y)
        
        f1(10)
        f2(10, 20)
}
実行結果:
10
10, 20

例 - Anonymous Function Syntax - 3

object Main extends Application {

    val f = (_ : int) + 1
    
    println( f(1) )
}
実行結果:
1
例:
object Main extends Application {

    def print(i: int, f: int => int ) {
        println( f(i) )
    }
    
    print(1, _ + 1)
    
}
実行結果:
2

例 - Anonymous Function Syntax - 4

object Main extends Application {

    val f = println( _: String )
    
    f("aaa")
}

実行結果:
aaa

例 - Anonymous Function Syntax - 5

object Main extends Application {

    class Person(name : String) {

        def getName() = name
    }
    
    val f = (_: Person).getName
    
    println( f(new Person("aaa")) )
    println( f(new Person("bbb")) )
}
実行結果:
aaa
bbb

例 - Currying

object Main extends Application {

    def sum(i: Int) : Int => Int = {

        def sumF(j: Int) : Int = {
            i + j
        }

    	sumF
    }
    val sumInts = sum(1)

    println( sumInts(2) ) // 3
実行結果:
3
短いバージョン:
object Main extends Application {

    def sum(i: Int)(j: Int) : Int = {
        i + j
    }

    val sumInts = sum(1) _ // "_" に注意
 
   println( sumInts(2) ) // 3
}
実行結果:
3

参考

例 - Currying - Function.curried

object Main extends Application {

    def sum(i: Int, j: Int) : Int =  {
        i + j
    }

    val curriedSum = Function.curried(sum _)
    
    println(curriedSum(1)(2)) // 3
}
実行結果:
3

例 - Currying - Function.uncurried

object Main extends Application {

    def sum(i: Int)(j: Int) : Int =  {
        i + j
    }
	
    val curriedSum = Function.uncurried(sum _)
    
    println(curriedSum(1, 2))
}
実行結果:
3

例 - Currying - 自分でやる - 1

object Main extends Application {

    def sum(i: Int, j: Int) : Int =  {
        i + j
    }
	
    val curriedSum = (x: Int) => (y: Int) => sum(x, y)
    
    println(curriedSum(1)(2))
}
実行結果:
3

例 - Currying - 自分でやる - 2

object Main extends Application {


    def sum(i: Int)(j: Int) : Int =  {
        i + j
    }
	
    val uncurriedSum = (x: Int, y: Int) => sum(x)(y)
    
    println(uncurriedSum(1, 2))
}
実行結果:
3

例 - By-Name Parameters - 1

object Main extends Application {

    def print(s: String) {
        println(s)
    }
    
    def call(proc: => Unit) {

        println("before call")
        
        proc
        
        println("after  call")
    }
    
    call( print("aaa")  )
    
    println()
    
    call( { print("aaa"); print("bbb") } )
}
実行結果:
before call
aaa
after  call

before call
aaa
bbb
after  call

例 - By-Name Parameters - 2

'('と')'を省略。
object Main extends Application {

    def print(s: String) {
        println(s)
    }
    
    def call(proc: => Unit) {
        
    	println("before call")
        
        proc
        
        println("after  call")
    }

    call { print("aaa") }
    
    println()
    
    call {
        print("aaa")
        print("bbb")
    }
}
実行結果:
before call
aaa
after  call

before call
aaa
bbb
after  call

例 - By-Name Parameters - 3

Unitである必要はありません。
object Main extends Application {
    
    def get1: Int = {
        println("get1")
    	1
    }
    def get2: Int = {
        println("get2")
        2
    }
    
    def call(e: => Int) {
        
    	println("before call")
        
        println(e) // 3
        
        println("after  call")
    }

    call { get1 + get2 }
}
実行結果:
before call
get1
get2
3
after  call

例 - By-Name Parameters - 4

object Main extends Application {
        
        def printOrNot(num: => int)(cond: => Boolean): Unit =
                if (cond) {
                        println(num)
                }

        printOrNot(1 + 2)(true)
        printOrNot(1 + 2)(false)
}
実行結果:
3

例 - Repeated Parameters

object Main extends Application {

    def printSum(args: Int*) {
        
        var result = 0
        
        for (arg <- args.elements) result += arg
     
        println(result)
    }
    
    printSum()
    printSum(1, 2)
    printSum(1, 2, 3)
}
実行結果:
0
3
6
Java バージョン:
public class Main {

	public static void main(String[] args) {
		
		printSum();
		printSum(1, 2);
		printSum(1, 2, 3);

	}
	
	private static void printSum(int... args) {
		
		int result = 0;
		for(int arg : args) {
			result += arg;
		}
		
		System.out.println(result);
	}
}

例 - By-Name Parameters - 5

object Main extends Application {
        
        def whileLoop(cond: => Boolean)(body: => Unit): Unit =
                if (cond) {
                        body
                        whileLoop(cond)(body)
                }
        
        var i = 10
        
        whileLoop (i > 0) {
                println(i)
                i = i - 1
        }
}
実行結果:
5
4
3
2
1

例 - Implicit Parameters - 1

object Main extends Application {
    
    abstract class MyImplicit {
        
        def print(i: int) {
            println("*** " + i + " ***")
        }
    }
    
    implicit object MyImplicit extends MyImplicit
    
    def print(i: int)(implicit my: MyImplicit) {
    	my.print(i)
    }

    print(1)
}
実行結果:
*** 1 ***

例 - Implicit Parameters - 2

object Main extends Application {
    
    abstract class MyImplicit[A] {
        def print(a: A)
    }
    
    implicit object MyImplicitInt extends MyImplicit[Int] {

        def print(i: Int) {
            println("int: " + i)
        }
    }

    implicit object MyImplicitString extends MyImplicit[String] {

        def print(s: String) {
            println("String: " + s)
        }
    }
    
    def print[A](a: A)(implicit my: MyImplicit[A]) {
    	my.print(a)
    }

    print(1) // int: 1
    print("aaa") // String: aaa
}
実行結果:
int: 1
String: aaa

例 - Implicit Conversions

object Main extends Application {

    class Person(val name: String)

    
    implicit def string2Person(name: String): Person = new Person(name);

    
    val p = "aaa";
	
    println( p.name )
}
実行結果:
aaa

例 - View Bounds - 1

object Main extends Application {
    
    class MyClass

    def viewTest[MyClass <% Int](my: MyClass) { // MyClass は Int に変換可能
        
        println("execute viewTest")
        
        val n = my + 1
        
        println(n)
    }
    
    
    implicit def my2int(my: MyClass): Int = {
    	
        println("execute my2int")

        1
    }

    viewTest(new MyClass)
}
実行結果:
execute viewTest
execute my2int
2
例:
object Main extends Application {
    
    class MyClass

    def viewTest[MyClass <% Int](my: MyClass) {
        
        println("execute viewTest")
        
        val n = my + 1
        
        println(n)
    }

    def test {

        implicit def my2int(my: MyClass): Int = {
            
            println("execute my2int")

            1
        }
        
        viewTest(new MyClass) // MyClassからIntに変換可能
    }

    test
    viewTest(new MyClass) // MyClassからIntに変換できないのでコンパイルエラー
}

例 - View Bounds - 2

object Main extends Application {
    
    def viewTest[T <% Int](t: T) {
        
        println("execute viewTest")
        
        val n = t + 1
        
        println(n)
    }

    class MyClassA
    class MyClassB

    implicit def myA2int(myA: MyClassA): Int = {
        
        println("execute myA2int")

        1
    }
    
    implicit def myB2int(myB: MyClassB): Int = {
        
        println("execute myB2int")

        2
    }

    viewTest( new MyClassA )
    viewTest( new MyClassB )
}
実行結果:
execute viewTest
execute myA2int
2
execute viewTest
execute myB2int
3

例 - View Bounds - 3

object Main extends Application {
    
    class MyClass

    def viewTest[T2, T1 <% T2](t1: T1, t2: T2) {
        
        val t: T2 = t1
        
        println(t)
    }

    implicit def my2int(my: MyClass): Int = {
        
        1
    }

    implicit def my2string(myA: MyClass): String = {
        
        "a"
    }
    viewTest(new MyClass, 1)
    viewTest(new MyClass, "a")
}
実行結果:
1
a

例 - Type Declarations and Type Aliases - 1

object Main extends Application {

   class MyClass {
     type S = String
   }

   val s1: MyClass#S = "aaa"
// val s2: MyClass#S = 111 コンパイルエラー
}

例 - Type Declarations and Type Aliases - 2

object Main extends Application {

   class MyClass {
     type MyList[T] = List[T]
   }

   val list1: MyClass#MyList[Int]    = List(1, 2, 3)

// val list2: MyClass#MyList[String] = List(1, 2, 3) コンパイルエラー
}

例 - Type Declarations and Type Aliases - 3

object Main extends Application {

   class MyClass {
     type Pair[T1, T2] = Tuple2[T1, T2]
   }

   val pair1: MyClass#Pair[Int, String] = (1, "aaa")

// val pair2: MyClass#Pair[Int, Int]    = (1, "aaa") コンパイルエラー
}

例 - Type Declarations and Type Aliases - 4

object Main extends Application {

   class MyClass {
     type %[T1, T2] = Tuple2[T1, T2]
   }

   val m = new MyClass
   
   import m._
   
   val pair: Int%String = (1, "aaa")

}

例 - Type Declarations and Type Aliases - 5

object Main extends Application {

    abstract class MyAbstractClass {        
        
        type MyType
        
        def m(t: MyType) = println(t)
    }
    
    class MyClass extends MyAbstractClass {        
        
        type MyType = String
    }

    new MyClass().m("a")
//  new MyClass().m(1) コンパイルエラー
}
実行結果:
a

例 - Type Declarations and Type Aliases - 6

object Main extends Application {

    abstract class AbstractComponent {
        type CompType
    }

    class ComponentA extends AbstractComponent {
        type CompType = String
    }
    class ComponentB extends AbstractComponent {
        type CompType = Int
    }

    
    class MyClass[T <: AbstractComponent] {        
        
        type MyType = T#CompType
        
        def m(my: MyType) = println(my)
    }
	
    val my1 = new MyClass[ComponentA]
    
    my1.m("a")
//  my1.m(1) コンパイルエラー
    
    val my2 = new MyClass[ComponentB]

//  my2.m("a") コンパイルエラー
    my2.m(1)  

}

実行結果:
a
1

例 - Structural Types - 1

object Main extends Application {

    class Person(name: String) {
        def getName: String = name
    }
    
    def printName(f: { def getName: String }) { println(f.getName) }

    
    printName( new Person("aaa") )
    
}
実行結果:
aaa

例 - Structural Types - 2

type との組み合わせ。
object Main extends Application {

    class Person(name: String) {
        def getName: String = name
    }
    
    type Name = { def getName: String }
    
    def printName(f: Name) { println(f.getName) }

    printName( new Person("aaa") )
}
実行結果:
aaa

例 - Structural Instance Creation Expression - 1

object Main extends Application {

  val o = new { def print = println("xxx") }

  o.print
}
実行結果:
xxx
Java との比較:
Java では、次のようにはできても
public class Main {

	public static void main(String[] args) {

		new Object() {
		
			public void print() {
				System.out.println("xxx");
			}
		
		}.print();
	}
}
次のようにはできません。
public class Main {

	public static void main(String[] args) {

		Object o = new Object() {
		
			public void print() {
				System.out.println("xxx");
			}
		
		};
		
		o.print(); // コンパイルエラー。Object クラスに print メソッドはない
	}
}

例 - Structural Instance Creation Expression - 2

object Main extends Application {
  
  def create = new { def print = println("xxx") }
  
  create.print
}
実行結果:
xxx
Java との比較:
Java では、明示的にメソッドの戻り値の型を指定する必要があるため、新たな型の定義が必要になります。
public class Main {
	
	interface Printer {
		public void print();
	}
	
	public static Printer create() {
		
		return new Printer() {
		
			public void print() {
				System.out.println("xxx");
			}
		};
	}
	
	public static void main(String[] args) {

		create().print();
	}
}

例 - Self Types - 1

object Main extends Application {

  trait MyTraitA {
    def print = println("MyTraitA.print")
  }
  
  trait MyTrait {
     this: MyTraitA =>
    
     def callPrint = {
       this.print
     }
   }
  
  val my = new MyTrait with MyTraitA

  my.callPrint
}
実行結果:
MyTraitA.print

例 - Self Types - 2

object Main extends Application {

  trait MyTraitA {
    def print = println("MyTraitA.print")
  }

  trait MyTraitB {
    def print = println("MyTraitB.print")
  }
  
  trait MyTrait {
    
     this: { def print } =>
    
     def callPrint = {
       this.print
     }
   }
  
  val my1 = new MyTrait with MyTraitA

  my1.callPrint

  
  val my2 = new MyTrait with MyTraitB

  my2.callPrint
}
実行結果:
MyTraitA.print

例 - Self Types - 3

object Main extends Application {

  trait Printer {
    def print = println("Printer.print")
  }
  class PrinterClient {
    def callPrint(p: Printer) = p.print
  }
  
  trait MyTrait {
    
     this: Printer =>
    
     def callClientPrint = {
       new PrinterClient().callPrint(this)
     }
   }

  class MyClass extends Printer;
  
  val my = new MyClass with MyTrait

  my.callClientPrint

}
実行結果:
Printer.print

例 - this.type - 1

object Main extends Application {

  class MyClass {
    
    def getThis: this.type = this

    def m = println("MyClass")
  }

  val my = new MyClass().getThis
 
  my.m
}
実行結果:
MyClass

例 - this.type - 2

object Main extends Application {

  class MyClass {
    
    def getThis: this.type = this

    def m = println("MyClass")
  }

  class MySubClass extends MyClass {
    
    def n = println("MySubClass")
  }

  val mySub = new MySubClass().getThis
  
  mySub.n
}
実行結果:
MySubClass

例 - this.type - 3

object Main extends Application {

  class MyClass {
    
    def getThis: this.type = new MyClass // コンパイルエラー
  }
}
インタプリタ:
scala> object Main extends Application {
     |
     |   class MyClass {
     |     def getThis: this.type = new MyClass
     |   }
     | }
:7: error: type mismatch;
 found   : Main.MyClass
 required: MyClass.this.type
           def getThis: this.type = new MyClass

例 - this.type - 4

object Main extends Application {

  class MyClass {
    def setThis(t: this.type) =  println(t)
  }
  
  val my1 = new MyClass
  val my2 = new MyClass

  my1.setThis( my1 )
  my1.setThis( my2 ) // コンパイルエラー
}

例 - this.type - 5

object Main extends Application {

  class MyClass {
    def setThis(t: this.type) =  println(t)
  }
  
  val my1 = new MyClass
  val my2 = new MyClass

  my1.setThis( my1 )
  my1.setThis( my2 ) // コンパイルエラー
}

例 - this.type - 6 - Generic Type との組み合わせ

object Main extends Application {

  class Container[T](val v: T)
  
  class MyClass {

    def createContainer = new Container[this.type](this)
    
    def printContainer(c: Container[this.type]) = println(c.v)
  }
  
  val my1 = new MyClass
  val my2 = new MyClass

  val c1 = my1.createContainer
  val c2 = my2.createContainer

  my1.printContainer(c1)
  my1.printContainer(c2) // コンパイルエラー
}

例 - onj.type - 1

object Main extends Application {

  class MyClass

  val my1 = new MyClass
  val my2 = new MyClass
  
  val my3: my1.type = my1
  val my4: my1.type = my2 // コンパイルエラー

  val my5: MyClass = my3
}

例 - onj.type - 2

object Main extends Application {

  class MyClass

  val my1 = new MyClass
  val my2 = new MyClass
  
  val my3: my1.type = my1
  val my4: my1.type = my2.asInstanceOf[my1.type] // キャストOK

  println(my3)
  println(my4)
}
実行結果:
test.obj_type.test02.Main$MyClass@dd20f6
test.obj_type.test02.Main$MyClass@19efb05

例 - onj.type - 3

object Main extends Application {

  class MyClass(val mys: String) {

    def print(s: mys.type) = println(s)
  }

  val my = new MyClass("aaa")
  
  my.print(my.mys)
  my.print("bbb") // コンパイルエラー
}

例 - apply method

object Main extends Application {

    class MyClass {
        def apply(i: int) = i;
    }

    val my = new MyClass
    println( my(10) ); // println( my.apply(10) ) と同じ
    
}
実行結果:
10

例 - List

object Main {
        
        def main(args : Array[String]) {
                
                val nums = List(1, 2, 3, 4, 5, 6, 7, 8)
                println( nums )
        }  
}
実行結果:
List(1, 2, 3, 4, 5, 6, 7, 8)

例 - Manifest - 1

object Main extends Application {
  
	class MyClass[T](implicit val manifest: scala.reflect.Manifest[T])
  
	println( new MyClass[String].manifest )
	println( new MyClass[Int].manifest )

	println

	println( new MyClass[String].manifest.erasure )
	println( new MyClass[Int].manifest.erasure )

}
実行結果:
java.lang.String
int

class java.lang.String
int

例 - Exception

package test.exception.test01;

object Main extends Application {
    
    class MyException extends Exception
    
    def m() {
        
        throw new MyException
    }
    
    try {
        m

    } catch {
        case e: MyException => println("Exception: " + e)
    }
}


実行結果:
Exception: test.exception.test01.Main$MyException

例 - Cast

cast には asInstanceOf メソッドを使います。
object Main extends Application {

    def test(any : Any) = {

        val s = any.asInstanceOf[String]

        println(s)
    }
    
    test("aaa")   
    test(100)   
}
実行結果:
aaa
Exception in thread "main" java.lang.ExceptionInInitializerError
	at test19.Main.main(Main.scala)
Caused by: java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
	at test19.Main$.test(Main.scala:6)
	at test19.Main$.(Main.scala:14)
	at test19.Main$.(Main.scala)
	... 1 more

例 - classOf

java.lang.Class オブジェクトの取得には classOf を使います。
object Main extends Application {

    class MyClass
    
    val clazz1 = classOf[MyClass]
    val clazz2 = classOf[String]
    
    println(clazz1)
    println(clazz1.getClass())

    println(clazz2)
    println(clazz1.getClass())
}
実行結果:
class test51.Main$MyClass
class java.lang.Class
class java.lang.String
class java.lang.Class
インタプリタ:
scala> class MyClass
defined class MyClass

scala> val clazz1 = classOf[MyClass]
clazz1: java.lang.Class[MyClass] = class MyClass

scala> val clazz2 = classOf[String]
clazz2: java.lang.Class[String] = class java.lang.String

例 - import - 1

package test.imp.test01.your

class YourClass {

}
package test.imp.test01.my;

import test.imp.test01.your.YourClass

object Main extends Application {
    
    val your = new YourClass
    
    println(your)
}
実行結果:
test.imp.test01.your.YourClass@a83b8a

例 - import - 2

package test.imp.test02.your

class YourClass {

}
package test.imp.test02.my

object Main extends Application {
    
  def m() = {

    import test.imp.test02.your.YourClass
    
    val your = new YourClass
    println(your)    
  }
  
  m()
  
//    val your = new YourClass // コンパイルエラー
//    println(your)      
    
}
実行結果:
test.imp.test02.your.YourClass@dd20f6

例 - import - 3

object Main extends Application {

  class MyClass {
    def method = println("MyClass.method")
  }
  
  val my = new MyClass
  
  import my._
  
  method
  
}
実行結果:
MyClass.method

例 - import - 4

object Main extends Application {

  class MyClass {
  
    class MyInnerClass {
      def method = println("MyInnerClass.method")
    }
  }
 
  val my = new MyClass
  
  import my._
  
  val myInner = new MyInnerClass
  
  myInner.method
  
}
実行結果:
MyInnerClass.method

例 - その他 - JFrame

import javax.swing.JFrame
import javax.swing.JFrame._

object Main extends Application {

    val f = new JFrame("My")
    f.setSize(100, 100)
    f.setDefaultCloseOperation(EXIT_ON_CLOSE)
    f.setVisible(true)
}
実行結果:

例 - Actor ライブラリ - 1

import scala.actors._

object Main extends Application {

    class MyActor extends Actor {

        def act() { // 抽象メソッドを実装
            println("act - start")
			
            var running = true

            while(running) {

                receive { // receive メソッド

                    case "end" =>
                       println("receive: end")
                       running = false

                    case msg: Any =>
                       println("receive: " + msg)
                }
            }
            println("act - end")
        }
    }
    
    val my = new MyActor
    my.start
    my ! "msg1" // ! メソッド は送信 (send) の意味
    my ! "msg2"
    my ! "end"
}
実行結果:
act - start
receive: msg1
receive: msg2
receive: end
act - end

例 - Parser Combinator ライブラリ - 1

import scala.util.parsing.combinator._

object MyParser extends RegexParsers {
  
  def leftParent: Parser[Any] = '('
}
object Main extends Application {
  
  import MyParser._
  
  println( parseAll( leftParent, "(" ) )

  println( parseAll( leftParent, "( " ) )

  println( parseAll( leftParent, " ( " ) )

  println( parseAll( leftParent, "((" ) )
}
実行結果:
[1.2] parsed: (
[1.3] parsed: (
[1.1] failure: `(' expected but   found
 
 ( 
^
[1.2] failure: string matching regex `\z' expected but `(' found

((

例 - Parser Combinator ライブラリ - 2

import scala.util.parsing.combinator._

object MyParser extends  RegexParsers {
  
  def leftParent: Parser[Any] = '('
}
object Main extends Application {
    
  import MyParser._
  
  parseAll( leftParent, "(" ) match {
    case Success(_, _) => println("Success")
    case Failure(_, _) => println("Failure")
  }

  parseAll( leftParent, ")" ) match {
    case Success(_, _) => println("Success")
    case Failure(_, _) => println("Failure")
  }

}
実行結果:
Success
Failure

例 - Parser Combinator ライブラリ - 3

object MyParser extends RegexParsers {

  def parent: Parser[Any] = "(" | ")"
}
object Main extends Application {
  
  import MyParser._
  
  println( parseAll( parent, "(" ) )

  println( parseAll( parent, ")" ) )

  println( parseAll( parent, "()" ) )
}
実行結果:
[1.2] parsed: (
[1.2] parsed: )
[1.2] failure: string matching regex `\z' expected but `)' found

()
 ^

例 - Parser Combinator ライブラリ - 4

import scala.util.parsing.combinator._

object MyParser extends JavaTokenParsers {
  
  def parent: Parser[Any] = "(" ~ ident ~ ")"
}
object Main extends Application {
  
  import MyParser._
  
  println( parseAll( parent, "(aaa)" ) )

  println( parseAll( parent, "( aaa )" ) )

  println( parseAll( parent, "( aaabbb )" ) )

  println( parseAll( parent, "( aaa ) ( bbb )" ) )
}
実行結果:
[1.6] parsed: (((~aaa)~))
[1.8] parsed: (((~aaa)~))
[1.11] parsed: (((~aaabbb)~))
[1.9] failure: string matching regex `\z' expected but ` ' found

( aaa ) ( bbb )
        ^

例 - Parser Combinator ライブラリ - 5

object MyParser extends JavaTokenParsers {
  
  def parent2: Parser[Any] = rep(parent)
  def parent: Parser[Any] = "(" ~ ident ~ ")" 
}
object Main extends Application {
  
  import MyParser._
  
  println( parseAll( parent2, "( aaa )" ) )

  println( parseAll( parent2, "(aaa) (bbb)" ) )

  println( parseAll( parent2, "(aaa) (bbb) (ccc)" ) )

  println( parseAll( parent2, "((aaa))" ) )
}
実行結果:
[1.8] parsed: List((((~aaa)~)))
[1.12] parsed: List((((~aaa)~)), (((~bbb)~)))
[1.18] parsed: List((((~aaa)~)), (((~bbb)~)), (((~ccc)~)))
[1.2] failure: string matching regex `[a-zA-Z_]\w*' expected but `(' found

((aaa))
 ^

例 - Parser Combinator ライブラリ - 6 - ^^ オペレータ

import scala.util.parsing.combinator._

object MyParser extends JavaTokenParsers {
  
  def parent: Parser[Any] = "(" ~ ident ~ ")" ^^ { case "(" ~ ident ~ ")" => "(" + ident + ")"}
}
object Main extends Application {
  
  import MyParser._
  
  println( parseAll( parent, "(aaa)" ) )

  println( parseAll( parent, "( aaa )" ) )

  println( parseAll( parent, "( aaabbb )" ) )
}
実行結果:
[1.6] parsed: (aaa)
[1.8] parsed: (aaa)
[1.11] parsed: (aaabbb)

参考文献とリソース

更新履歴

todo