Scala 특성에서 val 또는 def를 언제 사용합니까?
나는 통해가는 효과적인 스칼라 슬라이드 과 사용 결코 슬라이드 (10)에 언급 val
A의 trait
추상적 인 회원들과 사용을 위해 def
대신. 이 슬라이드는 왜 추상 val
을 사용하는 trait
것이 반 패턴 인지에 대해서는 자세히 언급하지 않습니다 . 누군가가 추상 방법의 특성에서 val 대 def를 사용하는 것에 대한 모범 사례를 설명 할 수 있다면 감사하겠습니다.
A def
는 def
, 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
할 수 있으므로 초기화 실패도 방지 할 수 있습니다.
나는 val
val 선언이 명확하지 않고 직관적이지 않은 초기화 순서를 가지고 있기 때문에 특성에 사용하지 않는 것을 선호합니다 . 이미 작동하는 계층 구조에 특성을 추가하면 이전에 작동했던 모든 것을 깨뜨릴 수 있습니다. 내 주제를 참조하십시오. 최종 클래스가 아닌 클래스에서 일반 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
'code' 카테고리의 다른 글
Vim에서 2 칸 들여 쓰기를 4 칸 들여 쓰기로 변경 (0) | 2020.09.20 |
---|---|
선택 옵션에서 체크 박스를 사용하는 방법 (0) | 2020.09.20 |
root 사용자를 제외하고 'test'@ 'localhost'사용자 (암호 사용 : YES)에 대한 액세스가 거부되었습니다. (0) | 2020.09.19 |
const void 란 무엇입니까? (0) | 2020.09.19 |
스레드는 Python에서 어떻게 작동하며 일반적인 Python- 스레딩 관련 함정은 무엇입니까? (0) | 2020.09.19 |