복붙노트

[SCALA] 때 스칼라의 특성에 발 또는 데프를 사용 하는가?

SCALA

때 스칼라의 특성에 발 또는 데프를 사용 하는가?

나는 유효 스칼라 슬라이드를 가고 있었다 그것은 추상적 인 회원의 특성에 발을 사용하지 않는 대신 데프 사용 결코 슬라이드 (10)에 언급하고있다. 형질에 추상적 발을 사용하는 이유를 구체적으로 언급하지 않는 슬라이드 안티 패턴이다. 누군가가 추상 메소드의 특성에 데프 대 발을 사용하여 주위에 모범 사례를 설명 할 수 있다면 나는 그것을 감사하겠습니다

해결법

  1. ==============================

    1.다음 DEF는 방어하는 발 게으른 발 또는 물체 중 하나에 의해 구현 될 수있다. 그래서 멤버를 정의하는 가장 추상적 인 형태입니다. 특성 말, 일반적으로 추상적 인 인터페이스이기 때문에 당신은 발을 구현해야하는 방법을 말하고 싶다. 당신이 발을 요청할 경우, 구현 클래스는 데프을 사용할 수 없습니다.

    다음 DEF는 방어하는 발 게으른 발 또는 물체 중 하나에 의해 구현 될 수있다. 그래서 멤버를 정의하는 가장 추상적 인 형태입니다. 특성 말, 일반적으로 추상적 인 인터페이스이기 때문에 당신은 발을 구현해야하는 방법을 말하고 싶다. 당신이 발을 요청할 경우, 구현 클래스는 데프을 사용할 수 없습니다.

    발은 당신이, 예를 들어, 안정적인 식별자를해야하는 경우에만 필요 경로 의존적 유형. 즉, 일반적으로 필요하지 않은 뭔가.

    비교:

    trait Foo { def bar: Int }
    
    object F1 extends Foo { def bar = util.Random.nextInt(33) } // ok
    
    class F2(val bar: Int) extends Foo // ok
    
    object F3 extends Foo {
      lazy val bar = { // ok
        Thread.sleep(5000)  // really heavy number crunching
        42
      }
    }
    

    당신이 있다면

    trait Foo { val bar: Int }
    

    당신은 F1 또는 F3을 정의 할 수 없습니다.

    좋아, 당신을 혼란 @ 대답하기 위해 OM-NOM-NOM-사용하여 초기화 문제가 발생할 수 있습니다 추상적 인 발스을 :

    trait Foo { 
      val bar: Int 
      val schoko = bar + bar
    }
    
    object Fail extends Foo {
      val bar = 33
    }
    
    Fail.schoko  // zero!!
    

    이것은 나의 개인적인 의견으로는 컴파일러에 고정하여 멀리 미래 스칼라 버전 가야 못생긴 문제이지만, 예, 현재이 또한 하나의 추상적 인 발스을 사용하지 말아야 이유입니다.

    편집 (년 1 월 2016) : 당신은 게으른 발 구현과 추상 발 선언을 재정의 할 수 있습니다, 그래서 또한 초기화 오류를 방지한다.

  2. ==============================

    2.발 선언이 초기화 불분명하고 비 직관적 인 순서를 가지고 있기 때문에 나는 특성에 발을 사용하지 선호합니다. 당신은 특성이 이미 계층 구조 작업을 추가 할 수 있으며, 전에 일을 모든 것을 파괴 내 항목을 볼 것입니다 : 왜 final이 아닌 클래스에서 일반 발을 사용하여

    발 선언이 초기화 불분명하고 비 직관적 인 순서를 가지고 있기 때문에 나는 특성에 발을 사용하지 선호합니다. 당신은 특성이 이미 계층 구조 작업을 추가 할 수 있으며, 전에 일을 모든 것을 파괴 내 항목을 볼 것입니다 : 왜 final이 아닌 클래스에서 일반 발을 사용하여

    당신은 결국 어떤 길 당신 오류로 염두에 발 선언을 사용하는 방법에 대한 모든 것을 유지해야합니다.

    그러나 당신이 발을 사용하여 피할 수있는 시간이있다. @ 0__ 때때로 언급했듯이 당신은 안정적인 식별자를 필요 데프는 아니다.

    나는 그가 얘기 한 것을 보여주기 위해 예를 제공합니다 :

    trait Holder {
      type Inner
      val init : Inner
    }
    class Access(val holder : Holder) {
      val access : holder.Inner =
        holder.init
    }
    trait Access2 {
      def holder : Holder
      def access : holder.Inner =
        holder.init
    }
    

    이 코드는 오류가 발생합니다 :

     StableIdentifier.scala:14: error: stable identifier required, but Access2.this.holder found.
        def access : holder.Inner =
    

    당신이 분 정도 걸릴 경우 해당 컴파일러가 불평 할 이유가 이해하는 것이라고 생각합니다. Access2.access의 경우는 어떤 방법으로 반환 유형을 도출 할 수 없었다. 데프 홀더는 다양한 방식으로 구현 될 수 있음을 의미한다. 그것은 각 호출에 대해 다른 소유자를 반환 할 수 있으며, 소유자는 다른 내부 유형을 통합하는 것. 그러나 자바 가상 머신은 동일한 유형이 반환 될 것으로 기대하고있다.

  3. ==============================

    3.항상이 같은 작동하지 않습니다 때문에 데프 조금 어색한 것 같다 사용 :

    항상이 같은 작동하지 않습니다 때문에 데프 조금 어색한 것 같다 사용 :

    trait Entity { def id:Int}
    
    object Table { 
      def create(e:Entity) = {e.id = 1 }  
    }
    

    다음과 같은 오류가 발생합니다 :

    error: value id_= is not a member of Entity
    
  4. from https://stackoverflow.com/questions/19642053/when-to-use-val-or-def-in-scala-traits by cc-by-sa and MIT license