IMCAT.DEV
로그인 가입
Scala 중급 객체지향

Scala 특질 (Traits)

Scala 특질 (Traits) — 중급

특질 (Traits)

1. 도입 (왜 배워야 하는가)

Scala에서 특질(Traits)은 객체 지향 프로그래밍에서 다중 상속의 문제를 해결하기 위한 강력한 도구입니다. 실무에서는 공통된 행동을 여러 클래스에 재사용할 수 있게 해주기 때문에 코드의 유지보수성과 가독성을 향상시킵니다. 특질을 사용하지 않으면 중복된 코드가 생기거나, 특정 클래스가 다른 클래스의 기능을 불필요하게 상속받아야 하는 상황이 발생할 수 있습니다. 이는 코드의 복잡성을 증가시키고, 버그를 유발할 수 있습니다.

2. 핵심 개념 설명

  • 특질(Trait): 클래스가 특정 행동을 구현할 수 있도록 정의된 일종의 인터페이스입니다. 특질은 클래스와 유사하지만 인스턴스를 만들 수 없고, 주로 상속을 통해 기능을 확장하는 데 사용됩니다.
  • 비유: 특질은 마치 '요리 레시피'와 같습니다. 레시피는 요리할 때 따라야 할 지침을 제공하지만, 요리 그 자체는 아닙니다. 각각의 요리사는 이 레시피를 바탕으로 자신의 스타일로 요리를 만들어냅니다.

    관련 용어 정리

    용어설명
    클래스객체를 생성하기 위한 청사진입니다.
    믹스인특질을 클래스에 추가하여 기능을 확장하는 방법입니다.
    다중 상속하나의 클래스가 여러 클래스로부터 상속받는 것입니다.

    3. 기본 코드 예제

    // 특질 정의
    trait Animal {
      def sound: String // 추상 메소드
    }
    
    // 특질을 상속받는 클래스
    class Dog extends Animal {
      def sound: String = "멍멍"
    }
    
    // 특질을 상속받는 또 다른 클래스
    class Cat extends Animal {
      def sound: String = "야옹"
    }
    
    // 객체 생성
    val dog = new Dog()
    val cat = new Cat()
    
    // 결과 출력
    println(dog.sound) // 멍멍
    println(cat.sound) // 야옹

    실행 결과

    멍멍
    야옹

    코드 설명

    1. trait Animal: Animal이라는 특질을 정의하며, sound라는 추상 메소드를 선언합니다.
    2. class Dog extends Animal: Dog 클래스가 Animal 특질을 상속받아 sound 메소드를 구현합니다.
    3. class Cat extends Animal: Cat 클래스도 마찬가지로 Animal 특질을 상속받고 sound 메소드를 구현합니다.
    4. val dog = new Dog(): Dog 클래스의 인스턴스를 생성합니다.
    5. val cat = new Cat(): Cat 클래스의 인스턴스를 생성합니다.
    6. println(dog.sound): dog 객체의 sound 메소드를 호출하여 결과를 출력합니다.
    7. println(cat.sound): cat 객체의 sound 메소드를 호출하여 결과를 출력합니다.
    8. 4. 실전 활용 예제

      예제 1: 쇼핑몰에서 장바구니를 구현할 때

      trait Item {
        def price: Double
      }
      
      class Book(val price: Double) extends Item
      class Electronic(val price: Double) extends Item
      
      class ShoppingCart {
        private var items: List[Item] = List()
      
        def addItem(item: Item): Unit = {
          items = item :: items
        }
      
        def totalPrice: Double = items.map(_.price).sum
      }
      
      // 사용 예
      val cart = new ShoppingCart()
      cart.addItem(new Book(29.99))
      cart.addItem(new Electronic(199.99))
      
      println(s"총 가격: ${cart.totalPrice}") // 총 가격: 229.98

      상황 설명: 이 예제에서는 Item 특질을 통해 여러 종류의 상품을 처리할 수 있는 장바구니를 구현했습니다. Book과 Electronic 클래스는 가격 정보를 제공하며, ShoppingCart는 이들 상품을 관리합니다.

      예제 2: 다양한 동물 소리 구현

      trait Sound {
        def makeSound(): String
      }
      
      class Dog extends Sound {
        def makeSound(): String = "멍멍"
      }
      
      class Cat extends Sound {
        def makeSound(): String = "야옹"
      }
      
      val animals: List[Sound] = List(new Dog(), new Cat())
      animals.foreach(animal => println(animal.makeSound()))

      상황 설명: 다양한 동물 클래스를 통해 다형성을 활용하여 각 동물의 소리를 출력합니다. Sound 특질을 사용하여 동물의 소리를 쉽게 확장할 수 있습니다.

      5. 흔한 실수와 주의사항

      실수 1: 특질의 추상 메소드를 구현하지 않기

      trait Animal {
        def sound: String
      }
      
      class Dog extends Animal {
        // def sound: String = "멍멍" // 구현하지 않음
      }
    9. 잘못된 코드: Dog 클래스가 sound 메소드를 구현하지 않았습니다.
    10. 올바른 코드: def sound: String = "멍멍" 메소드를 구현하여 오류를 해결합니다.
    11. 실수 2: 특질을 잘못 사용하기

      trait Vehicle {
        def drive(): Unit
      }
      
      class Car extends Vehicle {
        // drive 메소드 구현하지 않음
      }
      
      val car = new Car() // 오류 발생
    12. 잘못된 코드: Vehicle 특질의 drive() 메소드를 구현하지 않았습니다.
    13. 올바른 코드: def drive(): Unit = println("차가 달린다.")로 구현합니다.
    14. 6. 정리

    15. 특질은 다중 상속을 효과적으로 지원하여 코드의 재사용성을 높입니다.
    16. 특질을 통해 공통된 행동을 여러 클래스에 쉽게 적용할 수 있습니다.
    17. 특질은 클래스와 유사하지만 인스턴스를 생성할 수 없다는 점을 기억해야 합니다.
    18. 다음에 학습하면 좋은 주제: 믹스인(Mixin), 함수형 프로그래밍.