code

Scala 특성에서 val 또는 def를 언제 사용합니까?

codestyles 2020. 9. 19. 11:14
반응형

Scala 특성에서 val 또는 def를 언제 사용합니까?


나는 통해가는 효과적인 스칼라 슬라이드 과 사용 결코 슬라이드 (10)에 언급 valA의 trait추상적 인 회원들과 사용을 위해 def대신. 이 슬라이드는 왜 추상 val을 사용하는 trait것이 반 패턴 인지에 대해서는 자세히 언급하지 않습니다 . 누군가가 추상 방법의 특성에서 val 대 def를 사용하는 것에 대한 모범 사례를 설명 할 수 있다면 감사하겠습니다.


A defdef, a val, a lazy val또는 object. 그래서 이것은 멤버를 정의하는 가장 추상적 인 형태입니다. 트레이 트는 일반적으로 추상적 인 인터페이스이기 때문에 당신이 원한다고 val말하는 것은 구현이 어떻게해야 하는지를 말하는 것입니다. 을 요청 val하면 구현 클래스는 def.

A val는 안정적인 식별자가 필요한 경우에만 필요합니다 (예 : 경로 종속 유형). 그것은 일반적으로 필요하지 않은 것입니다.


비교:

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으로 대답합니다. abstract를 사용 val하면 초기화 문제가 발생할 수 있습니다.

trait Foo { 
  val bar: Int 
  val schoko = bar + bar
}

object Fail extends Foo {
  val bar = 33
}

Fail.schoko  // zero!!

이것은 내 개인적인 의견으로는 컴파일러에서 수정하여 향후 Scala 버전에서 사라져야하는 추악한 문제이지만, 현재 이것은 abstract를 사용해서는 안되는 이유이기도합니다 val.

편집 (2016 년 1 월) : 구현으로 추상 val선언 을 재정의 lazy val할 수 있으므로 초기화 실패도 방지 할 수 있습니다.


나는 valval 선언이 명확하지 않고 직관적이지 않은 초기화 순서를 가지고 있기 때문에 특성에 사용하지 않는 것을 선호합니다 . 이미 작동하는 계층 구조에 특성을 추가하면 이전에 작동했던 모든 것을 깨뜨릴 수 있습니다. 내 주제를 참조하십시오. 최종 클래스가 아닌 클래스에서 일반 val을 사용하는 이유

이 val 선언 사용에 대한 모든 것을 염두에 두어야 결국 오류가 발생합니다.


더 복잡한 예제로 업데이트

그러나 사용을 피할 수없는 경우가 있습니다 val. @ 0__이 언급했듯이 때때로 안정적인 식별자가 필요하며 def하나가 아닙니다.

나는 그가 말한 것을 보여주는 예를 제공 할 것입니다.

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 =

If you take a minute to think you would understand that compiler has a reason to complain. In the Access2.access case it could not derive return type by any means. def holder means that it could be implemented in broad way. It could return different holders for each call and that holders would incorporate different Inner types. But Java virtual machine expects the same type to be returned.


Always using def seems a bit awkward since something like this won't work:

trait Entity { def id:Int}

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

You will get the following error:

error: value id_= is not a member of Entity

참고URL : https://stackoverflow.com/questions/19642053/when-to-use-val-or-def-in-scala-traits

반응형