YourInteger 라는 스칼라 클래스를 생성하고, + 연산을 할 수 있는 메소드를 추가한다.

class YourInteger(i : Int) {
val number = i

def method(given : Int) = {
println("Hi " + given);
}

def plus(given : Int):YourInteger = {
new YourInteger(given + number)
}

override def toString() = {
"" + number
}
}



YourInteger 객체를 생성하고 + 연산을 해본다.

val a = new YourInteger(5);
println(a)

결과는 다음과 같다.

5



YourInteger 클래스의 method를 호출하면 당연히 잘 되지만, 반대의 케이스는 에러가 발생한다.

val b = a.method(1) // b는 컴파일 성공
val c = 1.method(3) // c는 컴파일 에러

컴파일러는 overloaded method value + with alternatives를 출력하는 에러가 발생한다.



암묵적 타입 변환인 implicit def를 선언하면, int에 대해 YourInteger의 메소드를 실행할 수 있다.  ruby처럼 static duck typing 기법에 대해서 조금 알았다.


val a = new YourInteger(5);
println(a)
implicit def intToYourInteger(x: Int) = new YourInteger(x);

val b = a.method(1)
val c = 1.method(3)
val d = 1.plus(2)






실행 코드에 implict 구문이 있으면 지저분해서 조금 변경할 수 있다.



YourInteger 클래스 파일에 YourInteger 객체를 선언한 후, 묵시적 타입 변환을 추가한다.



class YourInteger(i : Int) {
val number = i

def method(given : Int) = {
println("Hi " + given);
}

def plus(given : Int):YourInteger = {
new YourInteger(given + number)
}

override def toString() = {
"" + number
}
}


object YourInteger {

implicit def intToYourInteger(x: Int) = new YourInteger(x);

}



실행 코드에서 import를 하고..


import YourInteger._


실행할 메소드에서 다음을 사용하면 실행된다. 

val a = new YourInteger(5);
println(a)

val b = a.method(1)
val c = 1.method(3) println(c)
val d = 1.plus(2)



javap로 확인하면 다음과 같다.


$ javap YourInteger.class

Compiled from "YourInteger.scala"

public class YourInteger {

  public static YourInteger intToYourInteger(int);

  public int number();

  public void method(int);

  public YourInteger plus(int);

  public java.lang.String toString();

  public YourInteger(int);

}


$ javap YourInteger$.class

Compiled from "YourInteger.scala"

public final class YourInteger$ {

  public static final YourInteger$ MODULE$;

  public static {};

  public YourInteger intToYourInteger(int);

}


좀 더 내부를 파고 싶다면, class파일을 디컴파일하는 jad(http://varaneckas.com/jad/)를 이용한다. 


YourInteger.scala를 컴파일한 scala파일의 java 구현체(YourInteger, YourInteger$)는 다음과 같다. Predef 외에는 특별한 내용이 없다. 


import scala.Predef$;

import scala.collection.mutable.StringBuilder;

import scala.runtime.BoxesRunTime;


public class YourInteger

{


    public static YourInteger intToYourInteger(int i)

    {

        return YourInteger$.MODULE$.intToYourInteger(i);

    }


    public int number()

    {

        return number;

    }


    public void method(int given)

    {

        Predef$.MODULE$.println((new StringBuilder()).append("Hi ").append(BoxesRunTime.boxToInteger(given)).toString());

    }


    public YourInteger plus(int given)

    {

        return new YourInteger(given + number());

    }


    public String toString()

    {

        return String.valueOf(BoxesRunTime.boxToInteger(number()));

    }


    public YourInteger(int i)

    {

        number = i;

    }


    private final int number;

}






public final class YourInteger$

{


    public YourInteger intToYourInteger(int x)

    {

        return new YourInteger(x);

    }


    private YourInteger$()

    {

    }


    public static final YourInteger$ MODULE$ = this;


    static

    {

        new YourInteger$();

    }

}





실행 코드의 디컴파일 결과이다. 묵시적 타입 변환은 BoxedUnit이라는 클래스를 활용했다.



        YourInteger a = new YourInteger(5);

        Predef$.MODULE$.println(a);

        a.method(1);

        BoxedUnit b = BoxedUnit.UNIT;

        YourInteger$.MODULE$.intToYourInteger(1).method(3);

        BoxedUnit c = BoxedUnit.UNIT;
       Predef$.MODULE$.println(c);

        YourInteger d = YourInteger$.MODULE$.intToYourInteger(1).plus(2);




아래 scala 코드에 대한 자바코드를 살펴본다.

val c = 1.method(3) println(c)

1.method는 아래와 같은 자바 코드로 변환한다. 



        YourInteger$.MODULE$.intToYourInteger(1).method(3);

        BoxedUnit c = BoxedUnit.UNIT;

        Predef$.MODULE$.println(c);




Posted by '김용환'
,