Scala
예제 한빛 미디어 - 세븐 랭귀지
Loop
기본적인 while 루프는 아래와 같다.
def whileLoop {
var i = 1
while(i <= 3) {
println(i)
i += 1
}
}
whileLoop
스칼라의 함수는 기본적으로 public이 설정되어 있다.
for문의 경우에는 다른 언어와 조금 형식이 다르다.
def forLoop {
println( "for loop using Java-style iteration" )
for(i <- 0 until args.length) {
println(args(i))
}
}
forLoop
'초기값 until 마지막 값'
의 형태를 갖는 범위가 오게 된다.
루비의 each와 비슷한 foreach도 존재한다.
def rubyStyleForLoop {
println( "for loop using Ruby-style iteration" )
args.foreach { arg =>
println(arg)
}
}
rubyStyleForLoop
scala> val range = 0 until 10
range: scala.collection.immutable.Range = Range(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
scala> range.start
res26: Int = 0
scala> range.end
res27: Int = 10
scala> (0 to 5) by 1
res28: scala.collection.immutable.Range = Range(0, 1, 2, 3, 4, 5)
scala> val range = (10 until 0)(-1)
java.lang.IndexOutOfBoundsException: -1
at scala.collection.immutable.Range.apply$mcII$sp(Range.scala:151)
at scala.collection.immutable.Range.apply(Range.scala:149)
... 33 elided
scala> val range = (10 until 0)by (-1)
range: scala.collection.immutable.Range = Range(10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
scala> val range = (10 until 0)
range: scala.collection.immutable.Range = Range()
scala> val range = (0 to 10)
range: scala.collection.immutable.Range.Inclusive = Range(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
scala> val range = 'a' to 'z'
range: scala.collection.immutable.NumericRange.Inclusive[Char] = NumericRange(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z)
scala>
위 코드에서 보면 to의 경우 마지막 값을 포함하나, until은 마지막 값을 포함하지 않는다. 그리고 역으로 돌릴 수 있는데 그 때에는 -1로 방향을 지정해주어야 한다. 스칼라 컴파일러가 방향까지 유추하진 못한다.
튜플
스칼라는 튜플을 제공한다. 튜플은 길이가 고정된 객체 집합이다. 물론, 파이썬에서도 튜플이 존재한다. 튜플은 서로 자료형이 달라도 상관이 없다.
scala> val human = ("seungdols","seungdols comp")
human: (String, String) = (seungdols,seungdols comp)
scala> human._1
res29: String = seungdols
scala> human._2
res30: String = seungdols comp
아래와 같이 튜플을 이용해서 여러 변수에 한 번에 값을 넣어줄 수 있다.
튜플은 저장된 값을 이용해 정적 타이핑 검사를 수행할 수 있다.
scala> val (x,y) = (1,2)
x: Int = 1
y: Int = 2
Scala의 클래스
scala> class Human(firstName:String, lastName:String)
defined class Human
scala> val seungdols = new Human("seungdols","choi")
seungdols: Human = Human@47daf1
우선 위와 같이 선언할 수도 있지만, 더 알아보도록 하자.
아래 클래스를 살펴보자. 아래 클래스에서 중요한 특징을 찾을 수 있는데, 스칼라의 클래스 정의 부분에서 어떤 ‘함수’ 부분에 포함 되지 않은 부분이 Constructor(생성자)이다.
class Person(firstName: String) {
println("Outer constructor")
def this(firstName: String, lastName: String) {
this(firstName)
println("Inner constructor")
}
def talk() = println("Hi")
}
val bob = new Person("Bob")
val bobTate = new Person("Bob", "Tate")
class Person(firstName: String)//생성자 {
println("Outer constructor")
//this 이 부분이 보조 생성자이다.
def this(firstName: String, lastName: String) {
this(firstName)//메인 생성자 호출
println("Inner constructor")
}
}
짝 객체와 클래스 메서드
자바와 루비는 클래스 메서드와 인스턴스 메서드를 하나의 클래스 안에 만들 수 있었다.
자바에서 클래스 메서드는 static
키워드를 표시했고, 루비는 def self.class_method
를 이용했다. 스칼라는 이런 방법을 이용하지 않는다. 인스턴스 메서드는 class 정의 내부에서 선언한다. 그리고 그것이 하나의 객체 인스턴스만 갖는 다면, class 키워드 대신 object 키워드를 이용한다.
object TrueRing {
def rule = println("To rule them all")
}
TrueRing.rule
위 코드는 싱글턴객체를 생성한다.
클래스 메서드는 싱글턴 객체 선언 내에서, 인스턴스 메서드는 클래스 선언 내에서 선언할 수 있다.
class와 object를 같이 사용하는 방법을 companion Object(짝 객체)라고 부른다.
상속
스칼라에서 상속은 쉽다.
class Person(val name: String) {
def talk(message: String) = println(name + " says " + message)
def id(): String = name
}
class Employee(override val name: String,
val number: Int) extends Person(name) {
override def talk(message: String) {
println(name + " with number " + number + " says " + message)
}
override def id():String = number.toString
}
val employee = new Employee("Yoda", 4)
employee.talk("Extend or extend not. There is no try.")
생성자 및 확장하는 메서드는 앞에 ‘override’ 키워드를 반드시 작성해야 한다.
Trait
트레이트는 스칼라의 꽃이라 표현하고 싶다. (누가? 내가..)
C++는 다중상속, Java는 interface, Ruby는 mixin을 이용하므로, 스칼라도 뭔가를 이용해야 하지 않겠나. 그래서 트레이트를 사용하는데 이 개념은 Java의 interface의 개념으로 설명하면 구현된 interface라고 생각하면 될 것 같다. (물론 Java8에서 default 키워드로 method를 구현할 수 있게되었다.)
예시를 보고 배우자. 프로그래머는 예제로 배우면서 큰다.
class Person(val name:String)
trait Nice {
def greet() = println("Howdily doodily.")
}
class Character(override val name:String) extends Person(name) with Nice
val flanders = new Character("Ned")
flanders.greet
코드를 보면 Person 클래스를 확장하면서 Nice 트레이트를 혼합하고 있는 것을 볼 수 있다. 이렇게 하면 Character 인스턴스는 greet를 호출 할 수 있다.
Java8에서 interface에 default 키워드 붙인 느낌이랑 비슷하다.
세븐 랭귀지의 Scala 부분의 내용입니다.