Scala

[Scala] Programming in Scala - 6장. 함수형 객체

아이캔두이 2023. 1. 26. 14:15
728x90
반응형

 

우선 이번 장에서는 아래와 같은 개념을 알고 있다는 전제하에 학습을 진행합니다.

 

  • 클래스, 인스턴스
  • 필드(멤버변수), 메서드
  • 다형성, 상속
  • Public, Protected, Private
  • 오버로딩, 오버라이딩

 

모르는 부분이 있다면 검색해 봅시다.

 


1. 함수형 객체

함수형 프로그래밍의 원칙에 맞는 '변경 불가능한 객체'입니다.

 

장점 단점
  • 객체의 전달이 자유로움
  • 동기화 문제로 부터 자유로움
  • 안전한 해시테이블의 키
  • 간단한 변경으로 해결할 문제도 통째로 복사해야 하는 경우가 있음
    → 변경 가능한 클래스도 제공

 

 


2. 생성자

2.1 클래스 파라미터

  • 클래스 생성 시 파라미터를 넘길 수 있습니다.
  • 클래스 스코프 내에서 자유롭게 사용 가능하며, 필드(멤버변수)와는 다른 개념입니다.

 

2.2 주 생성자

  • 주 생성자의 형식은 클래스 파라미터로 결정됩니다.
  • 중괄호 레벨에 작성되는 코드는 주 생성자로 밀어 넣어집니다.
  • 중괄호 레벨에 정의한 변수들은 클래스의 필드(멤버변수)가 됩니다.
    • 함수형의 성질뿐 아니라, 마치 함수를 쓰듯이 작성하고 이것이 곧 객체가 됩니다.
class Sample(a: Int) {
    val num = a
    println("Primary Constructor")
}

val rat = new Sample(1)

 

2.3 보조 생성자

this 키워드는 다음 기능을 수행할 수 있습니다.

  • 자기 자신을 참조합니다.
  • 보조 생성자를 정의합니다.
class Sample(a: Int) {
 
  println(s"${a}")
 
  def this(a: Int, b: Int) = {
    this(a)
    println(s"${a}, ${b}")
  }
 
  def this(a : Int, b: Int, c: Int) = {
    this(a, b)
    println(s"${a}, ${b}, ${c}")
  }
 
}
 
val rat = new Sample(1, 2, 3)

1
1, 2
1, 2, 3

보조 생성자는 첫 줄에 다른 생성자를 호출해야 합니다. 그리고 결국 맨 마지막에는 주 생성자를 호출하며 끝내야 합니다.

 

 

 


3. 오버라이딩

예시를 통해 알아보도록 하겠습니다.

class Sample(n: Int) {
  override def toString() = {
    s"Sample : ${n}"
  }
}
 
println(new Sample(1))

Sample : 1

 

※ 오버라이딩과 오버로딩?
오버라이딩(Overriding) : 부모 클래스로부터 상속받은 메서드를 자식 클래스에서 재정의 하는 것입니다.
오버로딩(Overloading) : 한 클래스 내에 동일한 이름의 메서드가 있어도 매개변수의 개수 또는 타입이 다르다면, 동일한 이름을 사용해도 된다는 의미입니다.

 

 


4. 선결 조건 확인

함수의 로직을 실행하기 이전, 선결 조건을 확인할 수도 있습니다. 이 부분도 예시를 통해 알아보도록 하겠습니다.

아래는 require 메서드를 통해 값이 0이 아니어야 한다는 선결 조건을 추가해 준 것입니다.

 

class Sample(n: Int) {
  require(n != 0)
  override def toString() = {
    s"Sample : ${n}"
  }
}
 

println(new Sample(0))

Exception 발생

 

 


5. 비공개 필드와 메서드

  • Public, Protected, Private의 접근 제한자를 사용할 수 있습니다.
  • 필드, 메서드는 기본적으로 Public으로 설정되어 있습니다.
  • 함수나 변수 앞에 붙여서 사용합니다.(ex. private val num = 2)
  • 수식자 private [패키지명]으로 사용하여 어느 패키지까지 해당 제한자를 적용할지 설정할 수 있습니다.

 

 


6. 연산자 정의

연산자를 사용할 경우 아래의 두 경우는 같습니다.

a.add(b)
a add b

 

Scala는 함수명으로 연산자를 써도 전혀 이상할 것이 없습니다.

a.+(b)
a + b

 

※ 스칼라 스타일 가이드
기본적으로 CamelCase를 권장합니다.
  - 영숫자 식별자는 문자나 밑줄로 시작합니다.
  - 연산자 식별자는 하나 이상의 출력 가능한 아스키 문자입니다.
  - 리터럴 식별자는 `` 역따옴포 사이에 넣은 모든 것이 식별자가 됩니다. → 심지어 예약어도 지정 가능합니다.

단, 연산자 식별자는 컴파일러에서 해제되는 규칙이 존재합니다.
Scala가 아닌 Java에서 접근할 땐, 해제된 형태의 식별자로 접근해야 합니다.
ex) :-> → $colon$minus$greater

 

 

 


7. 암시적 타입 변환

사용하려는 스코프 내에 변환 메서드가 존재해야 합니다.

강력한 기능인만큼, 잘못 쓰게 되면 치명적이기 때문에 후에 자세히 다루기로 합시다.

implicit def intToRational(x: Int) = new Rational(x)

 

 

 

다음장에서는 스칼라의 내장 제어 구문에 대해 알아보도록 합시다 :)

 

[Scala] Programming in Scala - 7장. 내장 제어 구문

오랜만에 스칼라 학습 시간입니다. 오늘은 스칼라의 내장 제어 구문에 대해 알아보도록 하겠습니다. 스칼라가 제공하는 내장 제어 구문은 if, while, for, try, match, 함수 호출밖에 없습니다. 그리고

icandhee.com

 


[참고 도서]

  • Programming in Scala

 

728x90
반응형