클래스
클래스 (Classes)
객체 지향 언어에서 클래스는 객체를 만들기 위한 설계도예요. 스칼라의 클래스는 메서드·값·변수·타입·객체·트레이트·클래스를 멤버로 가질 수 있는데, 이들을 통틀어 _멤버_라고 불러요. 여기서는 클래스를 정의하고 생성자를 쓰고 접근을 제어하는 가장 기본적인 방법을 차근차근 살펴볼게요.
출처: 공식 문서 — Classes
클래스 정의하기
가장 간단한 클래스 정의는 class 키워드에 식별자 하나만 붙이면 끝이에요. 클래스 이름은 대문자로 시작하는 게 관례예요.
Scala 2에서는 new 키워드로 인스턴스를 만들고, Scala 3에서는 클래스를 함수처럼 User()로 호출해 인스턴스를 만들어요:
// Scala 2
class User
val user1 = new User
// Scala 3
class User
val user1 = User()
Scala 3에서도 new User()처럼 new 키워드를 명시적으로 쓸 수 있지만, 보통은 생략해요.
User는 생성자를 정의하지 않았기 때문에 인자를 받지 않는 기본 생성자를 가져요. 다만 보통은 생성자와 클래스 본문을 함께 쓰게 돼요. 점(Point)을 나타내는 클래스 예시를 볼게요:
// Scala 2
class Point(var x: Int, var y: Int) {
def move(dx: Int, dy: Int): Unit = {
x = x + dx
y = y + dy
}
override def toString: String =
s"($x, $y)"
}
val point1 = new Point(2, 3)
println(point1.x) // prints 2
println(point1) // prints (2, 3)
// Scala 3
class Point(var x: Int, var y: Int):
def move(dx: Int, dy: Int): Unit =
x = x + dx
y = y + dy
override def toString: String =
s"($x, $y)"
end Point
val point1 = Point(2, 3)
println(point1.x) // prints 2
println(point1) // prints (2, 3)
이 Point 클래스는 네 개의 멤버를 가져요. 변수 x·y와 메서드 move·toString이죠. 여기서 눈여겨볼 점은 주 생성자가 클래스 시그니처 (var x: Int, var y: Int)에 있다는 거예요. 많은 다른 언어와 달리 스칼라는 생성자 파라미터를 클래스 머리 부분에서 바로 받아요. move 메서드는 정수 인자 두 개를 받고 정보를 담지 않는 Unit 값 ()을 반환하는데, Java 계열 언어의 void와 비슷하다고 보면 돼요. 반면 toString은 인자를 받지 않고 String 값을 반환해요. toString은 AnyRef의 toString을 오버라이드하는 것이기 때문에 override 키워드를 붙였어요.
생성자 (Constructors)
생성자는 파라미터에 기본값을 줘서 선택적으로 만들 수 있어요:
// Scala 2
class Point(var x: Int = 0, var y: Int = 0)
val origin = new Point // x and y are both set to 0
val point1 = new Point(1) // x is set to 1 and y is set to 0
println(point1) // prints (1, 0)
// Scala 3
class Point(var x: Int = 0, var y: Int = 0)
val origin = Point() // x and y are both set to 0
val point1 = Point(1) // x is set to 1 and y is set to 0
println(point1) // prints (1, 0)
이 버전의 Point에서는 x·y가 기본값 0을 가지니까 아무 인자도 넘기지 않아도 돼요. 다만 생성자는 인자를 왼쪽에서 오른쪽으로 읽기 때문에, y 값만 넘기고 싶다면 파라미터 이름을 지정해야 해요:
// Scala 2
class Point(var x: Int = 0, var y: Int = 0)
val point2 = new Point(y = 2)
println(point2) // prints (0, 2)
// Scala 3
class Point(var x: Int = 0, var y: Int = 0)
val point2 = Point(y = 2)
println(point2) // prints (0, 2)
이렇게 이름을 지정해 쓰면 가독성도 함께 좋아져요.
private 멤버와 Getter/Setter 문법
멤버는 기본적으로 public이에요. private 접근 한정자를 붙이면 클래스 밖에서는 숨겨져요.
// Scala 2
class Point {
private var _x = 0
private var _y = 0
private val bound = 100
def x: Int = _x
def x_=(newValue: Int): Unit = {
if (newValue < bound)
_x = newValue
else
printWarning()
}
def y: Int = _y
def y_=(newValue: Int): Unit = {
if (newValue < bound)
_y = newValue
else
printWarning()
}
private def printWarning(): Unit =
println("WARNING: Out of bounds")
}
val point1 = new Point
point1.x = 99
point1.y = 101 // prints the warning
// Scala 3
class Point:
private var _x = 0
private var _y = 0
private val bound = 100
def x: Int = _x
def x_=(newValue: Int): Unit =
if newValue < bound then
_x = newValue
else
printWarning()
def y: Int = _y
def y_=(newValue: Int): Unit =
if newValue < bound then
_y = newValue
else
printWarning()
private def printWarning(): Unit =
println("WARNING: Out of bounds")
end Point
val point1 = Point()
point1.x = 99
point1.y = 101 // prints the warning
이 버전의 Point에서는 데이터를 private 변수 _x·_y에 저장해요. def x·def y는 그 private 데이터에 접근하는 메서드이고, def x_=·def y_=는 _x·_y 값을 검증하고 설정하는 세터예요. 세터의 특별한 문법을 눈여겨보세요 — 메서드 이름에 getter의 식별자 뒤로 _=를 붙이고, 파라미터는 그 뒤에 와요.
주 생성자 파라미터에 val이나 var를 붙이면 public이 돼요. 그런데 val은 불변이기 때문에 다음 코드는 쓸 수 없어요:
// Scala 2
class Point(val x: Int, val y: Int)
val point = new Point(1, 2)
point.x = 3 // <-- does not compile
// Scala 3
class Point(val x: Int, val y: Int)
val point = Point(1, 2)
point.x = 3 // <-- does not compile
val·var가 붙지 않은 파라미터는 private 값이라 클래스 안에서만 보여요:
// Scala 2
class Point(x: Int, y: Int)
val point = new Point(1, 2)
point.x // <-- does not compile
// Scala 3
class Point(x: Int, y: Int)
val point = Point(1, 2)
point.x // <-- does not compile
더 알아보기
- 통합 타입 (Unified Types) —
AnyRef등의 타입 계층 - 케이스 클래스 (Case Classes) — 일반 클래스와의 차이점
- 트레이트 (Traits) — 클래스에 동작을 섞는 방법