Scala class, object, trait

Minseop Jeong·2022년 2월 5일
0

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개의 댓글