Scala class, object, trait

Minseop Jeong·2022년 2월 5일

scala는 함수형 프로그래밍언어 이기도 하면서 java, python과 같이 객체지향 프로그래밍언어 이기도 하다. scala에서 객체를 정의하는 방법에 대해 알아보자.

object

하나의 인스턴스 밖에 가질 수 없는 클래스, singleton 객체이다. 객체를 직접 생성하는 대신 아래와 같이 이름으로 해당 객체에 직접 접근한다.

object Validator {
  def validate(stamp: Stirng): Unit = {...}
}

Validator.validate(...)

해당 객체는 reference 될 때 lazy하게 instantiate 된다. scala에는 static keyword가 존재 하지 않고, static하길 원하는 멤버(i.e. main)는 singletone 객체인 object에 선언한다.

class

java의 class와 동일하다. 단 constructor가 따로 존재 하지 않으며, method 밖의 모든 라인이 객체 instantiate시 사용된다. 아래와 같이 정의할 수 있다.

class Connector(user: String, password: String) {
  val connection = ...
  def connect(): Unit = {...} 
} 

아래와 같이 객체를 생성할 수 있다.

val dbConnector = new Connector(conf.user, conf.password)

case class

일반적인 class와 비슷하지만 조금 다른 점이 있다. 아래와 같이 정의 후 사용할 수 있다.

case class Connector(user: String, password: String)

val dbConnector = Connector(conf.user, conf.password)

new keyword가 사용이 안된다. 자동으로 생성되는 메소드(i.e. apply, toString, ...)가 클래스에 포함되어 객체 생성에 사용되기 때문이다. case class는 immutable한 데이터를 표현할 때 유용하며, 패턴 매칭에도 도움이 된다. 이 부분은 추후 정리하겠다.

반면 case class는 계층적인 클래스 구조에서는 유용하지 않을 수 있다. 자동 생성되는 메소드들은 서브 클래스에 새로 추가되는 필드들을 고려하지 않고, 따라서 case class를 상속받는 class에서 자동 생성된 메소드들을 사용시 유효하지 않은 결과를 가져올 수 있다.

trait

trait은 java의 interface와 유사하며, class간에 interface와 필드를 공유하는 데 사용된다. trait은 instantiate 될 수 없다. 다음과 같이 정의할 수 있다.

trait Iterator[A] {
  def hasNext: Boolean
  def next(): A
}

제너릭 타입을 사용하여 trait을 정의하였다. 따라서 재사용성이 좋다. 정의한 trait을 상속받는 class를 아래와 같이 선언하였다.

class IntIterator(to: Int) extends Iterator[Int] {
  private var current = 0
  override def hasNext: Boolean = current < to
  override def next(): Int = {
    if (hasNext) {
      val t = current
      current += 1
      t
    } else 0
  }
}

Reference

profile
Data Engineer

0개의 댓글