본문 바로가기
language/Scala

[Scala] 스칼라 배우기 4. 스칼라 기본 문법3(클래스)

by 스파이디웹 2023. 5. 23.
728x90

클래스(class)

클래스는 class를 이용하여 생성

// 클래스 선언 
class Person(name:String, age:Int)
// 클래스 생성 
val p = new Person("David", 30)

// 멤버 변수 생략 가능 
class A

클래스 멤버 변수

  • 가변 변수는 컴파일러가 클래스 내부에 자동으로 getter, setter 메소드를 생성
  • 가변 변수로 선언된 값은 읽고, 쓰는 것이 가능
  • 불변 변수는 컴파일러가 getter만 생성,. 불변 변수로 선언된 값은 읽는 것만 가능
  • 가변 변수, 불변 변수로 선언되지 않은 변수는 getter, setter 가 생성되지 않기 때문에 클래스 내부에서만 사용할 수 있음
// 기본형 
class Animal(name: String) {
  println(s"${name} 생성")
}

// 가변
class Dog(var name: String) {
  println(s"${name} 생성")
}

// 불변 
class Cat(val name: String) {
  println(s"${name} 생성")
}

var ani = new Animal("동물")
var dog = new Dog("개")
var cat = new Cat("고양이")

 

멤버변수의 디폴트 값

  • 클래스 멤버변수는 변수의 종류에 상관없이 디폴트 값을 입력할 수 있음
  • 멤버변수의 값을 입력하지 않으면 디폴트 값을 이용
// 기본 멤버 변수, 변수, 상수 모두 기본값 설정 가능 
class Person1(name:String, age:Int)
class Person2(var name:String, var age:Int = 10)
class Person3(val name:String="Ted", val age:Int)

var p1 = new Person1("David", 12)
var p2 = new Person2("Tomphson")
var p3 = new Person3("David", 12)

// name 에 기본값을 입력할 수 없어서 오류 발생 
var p3 = new Person3(12)  
scala> var p3 = new Person3(12)
<console>:13: error: not enough arguments for constructor Person3: (name: String, age: Int)Person3.
Unspecified value parameter age.
       var p3 = new Person3(12)
                ^

클래스의 메소드

함수선언과 동일하게 def로 선언

class Person(name:String, age:Int) {
    def greeting() = println(s"${name}님은 ${age}살 입니다.")
}

메소드 오버라이딩(override)

  • override 선언자를 이용하여 메소드를 오버라이드 할 수 있음
  • new를 이용하여 클래스 생성시에 오버라이드하여 메소드를 재정의할 수 있음
class Person(name:String, age:Int, val job:String) {
    def greeting() = println(s"${name}님은 ${age}살 입니다.")
    def work() = println(s"직업은 ${job}입니다. ")
}

// work 함수 오버라이딩 
class Writer(name:String, age:Int) extends Person(name, age, "") {
    override def work() = println(s"직업은 작가입니다.")
}

scala> w.greeting
David님은 15살 입니다.

scala> w.work
직업은 작가입니다.

// 클래스 생성시 메소드 오버라이드. public 변수를 사용하는 메소드만 오버라이드 가능 
val p = new Person("David", 15, "학생") {
  override def work() = println(s"job is ${job}. ")
}

생성자

  • 스칼라는 따로 생성자가 존재하지 않음
  • 클래스 바디부분에 있는 코드가 바로 실행되기 때문에 이 부분에 처리 로직을 넣어주면 됨
class Person(name:String, age:Int) {
    def greeting() = println(s"${name}님은 ${age}살 입니다.")
    println("초기화 완료")
}

추상 클래스

  • 추상클래스는 abstract를 이용
  • 추상클래스는 매개변수를 가질 수 있음
  • 소드를 선언만 하고 구현은 자식 클래스에 맡길 수도 있고 기본 메소드를 구현할 수도 있음
// 추상클래스 선언 
abstract class Person(name: String, age: Int) {
  def work
  def status(str: String)
  def greeting() = println(s"${name}님은 ${age}살 입니다.")
}

상속

  • 상속은 extends를 이용
  • 일반 클래스와 추상클래스 모두 상속할 수 있음
// Person 추상 클래스를 상속 
class Player(name: String, age: Int) extends Person(name, age) {
  def work = { println("일합니다.") }
  def status(str: String) = println(s"$str 상태 입니다.")
}

봉인 클래스(sealed class)

  • 봉인 클래스는 하위 타입이 모두 한파일에 있어야 함
  • 관련 클래스를 한파일에 모두 입력하게 강제할 수 있기 때문에 관리의 효율성이 높아짐
  • 봉인 클래스는 sealed를 이용하고 트레잇도 봉인할 수 있음
// file1.scala
sealed abstract class Furniture
case class Couch() extends Furniture
case class Chair() extends Furniture

// file2.scala
case class Desk() extends Furniture
  -> illegal inheritance from sealed class Furniture

케이스 클래스(case class)

  • 스칼라에는 케이스 클래스라는 특수 클래스가 존재
  • case를 이용하여 생성
  • 일반 클래스와 달리 인스턴스를 생성할 때 new를 사용하지 않음
// 케이스 클래스 Person 선언 
case class Person(name:String, age:Int)

var p = Person("철수", 15)

특징

불변 데이터

  • 케이스 클래스의 멤버변수는 기본적으로 불변 변수로 선언
case class Person(name:String, age:Int)

var p = Person("A", 10)

scala> p.name
res6: String = A

// 케이스 클래스의 데이터는 불변 변수로 자동 선언 
scala> p.name = "B"
<console>:27: error: reassignment to val
       p.name = "B"
              ^

패턴매칭

  • 스칼라의 패턴매칭은 자바 case문과 유사
  •  자바의 switch 문과 유사하지만, 자바와는 달리 기본 자료형외에 케이스 클래스를 이용한 처리가 가능
  • aram의 값이 value1의 값과 비교되어 일치하는 값의 결과를 반환
  • 언더바(_)는 어떤 값도 일치하지 않을 때 처리 결과를 출력
param match {
  case value1 => "value1"
  case _ => "default value"
}

데이터 비교

  • 케이스 클래스의 비교는 참조값을 이용하지 않고, 클래스의 멤버변수의 데이터를 이용하여 처리
var p1 = Person("A", 10)
var p2 = Person("A", 10)
var p3 = Person("B", 10)

scala> p1 == p2
res7: Boolean = true

scala> p2 == p3
res8: Boolean = false

초기화가 간단

  • 케이스 클래스는 new를 이용하지 않고 초기화 할 수 있음
  • 키워드를 이용하지 않기 때문에 문법적으로 더 간단하고 효율적으로 표현
var p = Person("A", 10)

자동 코드 생성

  • 컴파일러가 tostring, hashcode, equals를 자동으로 생성
  • 컴파일러가 불변 객체를 지원하기 위해서, 새로운 복제 객체를 리턴하는 copy() 메서드를 자동으로 생성
var p = Person("A", 10)

scala> p.toString
res9: String = Person(A,10)

scala> p.hashCode
res10: Int = 649684425

믹스인 컴포지션(mix in composition)

믹스인 컴포지션은 클래스와 트레잇을 상속할 때 서로 다른 부모의 변수, 메소드 를 섞어서 새로운 정의를 만드는 것

abstract class A {
  val message: String
}

class B extends A {
  val message = "I'm an instance of class B"
}

trait C extends A {
  def loudMessage = message.toUpperCase()
}
// 클래스 D는 클래스 B와 트레잇 C를 믹스인하여 클래스 B의 message 를 이용하는 loudMessage 함수를 생성할 수 있음
class D extends B with C


scala> val d = new D
d: D = D@2c674d58

scala> println(d.message) 
I'm an instance of class B

scala> println(d.loudMessage)
I'M AN INSTANCE OF CLASS B

 

 

 

출처:

https://wikidocs.net/29773

728x90

댓글