멤버 (즉, 중첩) 형식을 사용하면 의존적 메서드 형식이 필요할 수 있습니다. 특히, 나는 의존적 인 방법 유형이 없으면 고전적인 케이크 패턴이 반 패턴에 더 가깝다고 유지합니다.
그래서 무엇이 문제입니까? 스칼라의 중첩 유형은 둘러싼 인스턴스에 따라 다릅니다. 결과적으로 종속 메소드 유형이없는 경우 해당 메소드 외부에서이를 사용하려는 시도는 매우 어려울 수 있습니다. 이것은 처음에는 우아하고 매력적으로 보이는 디자인을 악몽처럼 단단하고 리팩토링하기 어려운 괴물로 바뀔 수 있습니다.
고급 스칼라 훈련 과정 에서 제공하는 운동을 통해
trait ResourceManager {
type Resource <: BasicResource
trait BasicResource {
def hash : String
def duplicates(r : Resource) : Boolean
}
def create : Resource
// Test methods: exercise is to move them outside ResourceManager
def testHash(r : Resource) = assert(r.hash == "9e47088d")
def testDuplicates(r : Resource) = assert(r.duplicates(r))
}
trait FileManager extends ResourceManager {
type Resource <: File
trait File extends BasicResource {
def local : Boolean
}
override def create : Resource
}
class NetworkFileManager extends FileManager {
type Resource = RemoteFile
class RemoteFile extends File {
def local = false
def hash = "9e47088d"
def duplicates(r : Resource) = (local == r.local) && (hash == r.hash)
}
override def create : Resource = new RemoteFile
}
그것은 고전적인 케이크 패턴의 예 : 우리는 점차적으로 계층 구조를 통해 정제하는 추상화의 가족이 ( ResourceManager
/ Resource
에 의해 정제되어 FileManager
/ File
에 의해 정제 차례로있는 NetworkFileManager
/ RemoteFile
). 장난감 예제이지만 패턴은 실제입니다. Scala 컴파일러 전체에서 사용되며 Scala Eclipse 플러그인에서 광범위하게 사용되었습니다.
다음은 사용중인 추상화의 예입니다.
val nfm = new NetworkFileManager
val rf : nfm.Resource = nfm.create
nfm.testHash(rf)
nfm.testDuplicates(rf)
경로 의존성은 컴파일러가 on testHash
과 testDuplicates
메소드 NetworkFileManager
가 이에 대응하는 인수로만 호출 될 수 있음을 보증한다는 것을 참고하십시오 . 그것은 자신의 RemoteFiles
것이고 다른 것은 없습니다.
이것은 바람직한 속성이지만,이 테스트 코드를 다른 소스 파일로 옮기고 싶었다고 가정 해보십시오. 종속 메소드 유형을 사용하면 ResourceManager
계층 외부에서 해당 메소드를 쉽게 재정의 할 수 있습니다 .
def testHash4(rm : ResourceManager)(r : rm.Resource) =
assert(r.hash == "9e47088d")
def testDuplicates4(rm : ResourceManager)(r : rm.Resource) =
assert(r.duplicates(r))
여기에서 종속 메소드 유형의 사용에 주목하십시오. 두 번째 인수 ( rm.Resource
) 의 유형은 첫 번째 인수 ( rm
) 의 값에 따라 다릅니다 .
의존적 인 메소드 유형 없이이 작업을 수행 할 수는 있지만 매우 어색하고 메커니즘은 매우 직관적이지 않습니다. 나는 거의 2 년 동안이 과정을 가르치고 있으며 그 당시 아무도 신속하게 작동하는 솔루션을 찾지 못했습니다.
직접 해보십시오 ...
// Reimplement the testHash and testDuplicates methods outside
// the ResourceManager hierarchy without using dependent method types
def testHash // TODO ...
def testDuplicates // TODO ...
testHash(rf)
testDuplicates(rf)
잠시 동안 어려움을 겪고 나면 왜 내가 (또는 아마도 데이비드 맥 이버 였는지, 우리가 어느 용어를 만든 지 기억 나지 않습니다) 이것을 이것을 빵집 베이커리라고 부릅니다.
편집 : 합의는 운명의 빵집이 David MacIver의 주화였습니다 ...
보너스 : 스칼라의 종속 유형 (종종 종속 메소드 유형)은 프로그래밍 언어 베타 에서 영감을 얻었습니다 . 베타의 일관된 중첩 의미론에서 자연스럽게 발생합니다. 나는이 형태의 의존 유형을 가진 희미한 주류 프로그래밍 언어조차 모른다. Coq, Cayenne, Epigram 및 Agda와 같은 언어는 좀 더 일반적인 방식으로 다른 형태의 의존적 타이핑을 가지고 있지만 스칼라와 달리 서브 타이핑이없는 타입 시스템의 일부이기 때문에 크게 다릅니다.