Scala Trait 사용 예

7255 단어 mixinScalatrait

목표



Scala의 Trait이 어떻게 기쁜지 논의합니다.

주의



Scala의 Trait는 엄밀하게는 Mixin이므로, 이후의 문장에서는 Mixin이라는 말을 사용합니다만, 특별히 신경쓰지 않는다고 하는 사람은 Mixin을 Trait로 옮겨 읽어 주세요.

Mixin의 간략한 설명



하나의 클래스가 여러 개의 다른 클래스의 기능을 갖도록 다중 상속 할 때 여러 부모 클래스가 동일한 이름의 멤버 변수 또는 함수를 가질 때 하위 클래스는이 이름의 멤버에 액세스 할 때 의 부모 클래스의 멤버에 액세스하면 좋은지 모호해진다. Mixin을 사용하면 상속 순서 관계를 밝힐 수 있으며 하위 클래스에서 Mixin의 상속 대상을 결정할 수 있으므로 상속 대상 클래스를 하위 클래스에서 유연하게 결정할 수 있습니다.

사용 예



전자 화폐 지갑과 같은 외부 서버와 API를 통해 협력하는 응용 프로그램의 구현을 가정합니다. 지갑은 잔액을 유지하고 다른 지갑의 주소를 지정하여 돈을 송금하는 기능을 가지고 있습니다. 이 기능은 API를 통해 다른 지갑의 잔액을 늘린 다음 자체 잔액을 줄입니다.

이 예에서는, 외부 서버와 연동하는 대신에 테스트용 서버와 연동하는 API를 사용하는 테스트용 지갑을 구현할 때, Mixin 기능이 유효하게 작동하는 것을 클래스 다이어그램을 사용하여 나타낸다.



테스트 용 지갑 (TestModeWallet)은 프로덕션 용 지갑과 유사한 기능을 제공하는 것 외에도 테스트 용 서버와 함께 작동하는 TestMode의 기능을 제공하고자합니다. 따라서 TestModeWallet은 두 클래스를 상속하고 싶지만 두 가지는 callPayAPI라는 같은 이름의 메서드를 가지므로 다중 상속 중에 어느 클래스의 메서드를 우선 할지 모호합니다. 여기서 Mixin을 도입하면 상위 클래스의 상속 관계에 순서를 지정할 수 있습니다. 상속 관계는 TestModeWallet <: TestMode <: Wallet입니다.

또한 Wallet과는 별도로 API를 통해 외부 서버와 연계하는 Account 클래스가 존재하며, 이것을 테스트하기 위해 확장 할 때 TestMode의 상속 대상을 Account 클래스가되도록 TestModeAccount를 정의 할 수 있습니다. . 상속 관계는 TestModeAccount <: TestMode <: Account입니다.

Mixin을 사용하면 자식 클래스가 Mixin의 상속 대상을 결정할 수 있으므로 여러 클래스에 Mixin에서 정의한 기능을 제공 할 수 있습니다.

코딩 예:
// テストモードにしたいクラスはこの Mixin を継承すると,テスト用の API を使うようになる.
trait TestMode {
  def callPayAPI(amount: Int, address: String){
    TestAPI.pay(amount, address)
  }
  def callSetIDAPI(oldID: Int, newID: Int){
    TestAPI.setID(oldID, newID)
  }
}

// テスト用のサーバの挙動.
object TestAPI {
  def pay(amount: Int, address: String){} // TestMode causes nothing.
  def setID(oldID: Int, newID: Int) {}// TestMode causes nothing.
}

class Wallet {
  var balance = 0
  def pay(amount: Int, address: String){
    callPayAPI(amount, address)
    balance = balance - amount
  }
  def callPayAPI(amount, address){
    API.pay(amount, address) // This calls actual API.
  }
}

class Account {
  val id = 1
  def setID(newID: Int){
    callSetIDAPI(id, newID)
    id = newID
  }
  def callSetIDAPI(oldID: Int, newID: Int){
    API.setID(oldID, newID) // This calls actual API.
  }
}

// Wallet class for test mode.
class TestModeWallet extends Wallet with TestMode {}
// Account class for test mode.
class TestModeAccount extends Account with TestMode {}

Mixin 기능이 없는 경우의 고찰



Mixin의 기능이 없다고 가정하면 몇 가지 구현 제약이 발생합니다.
Mixin이 없고 TestModeWallet이 TestMode와 Wallet을 다중 상속하도록 구현하면 TestMode와 Wallet 모두에 callPayAPI 메서드가 있으므로 메서드 호출자에게 모호성이 발생합니다. TestMode를 제거하고 TestModeWallet에서 callPayAPI 메소드를 정의하는 경우 TestAPI를 다른 테스트 용 API로 바꿀 때 여러 클래스 정의에서 구현을 변경해야하는 문제가 발생합니다.

좋은 웹페이지 즐겨찾기