2011-09-09 34 views
8

Tôi có một số mã bất biến mà đối tượng phải được xây dựng trong hàm mà nó được sử dụng cuối cùng (vì nhiều lý do liên quan đến trạng thái toàn cầu không lý tưởng. của giả định).Kiểm tra thời gian biên dịch Scala cho vị trí của các hàm tạo (constructor)

ví dụ: Giả sử có hàm boo bên dưới có trách nhiệm thao tác moo.

def boo(mooGen:() => Moo) { 
    val m = mooGen() // a new MOO must be created HERE 
    m.moo() 
} 

Khách hàng của boo muốn sử dụng phải vượt qua một loại() => Moo, trong đó chức năng tạo Moo mong muốn.

lý tưởng hành vi khách hàng:

boo(() => new Moo(// specific parameters here)) 

Các Moo không được tạo ra cho đến khi bên trong cơ thể boo.

Tuy nhiên, một khách hàng có thể dễ dàng sai lầm với đoạn mã sau:

val myMoo = new Moo(// specific parameters here) 
boo(() => myMoo) 

này phá vỡ bất biến mà chúng ta muốn xây dựng moo xảy ra chỉ trong boo. Vì vậy, về cơ bản, tôi muốn xác định xem giá trị trả về của mooGen có được tạo trong ngăn xếp cuộc gọi của hàm hay liệu nó đã được tạo trước đó hay chưa.

Có nhiều cách để xác minh điều này khi chạy. Tuy nhiên, có cách nào để buộc mẫu này tại số biên dịch không? Sử dụng implicits hoặc bất cứ điều gì khác thông minh?

Bất kỳ ý tưởng nào được đánh giá cao!

Trả lời

12

Đặt boo và Moo vào đối tượng riêng của chúng, cùng với một lớp Token, không thể được khởi tạo bên ngoài đối tượng.

scala> object Foo { 
    | class Moo(token:Token) {} 
    | class Token private[Foo]() 
    | def boo(mooGen: (Token) => Moo) {val m = mooGen(new Token)} 
    | } 
defined module Foo 

Bây giờ những gì bạn muốn có thể được thực hiện:

scala> Foo.boo(new Foo.Moo(_)) 

Và những gì bạn không muốn không thể được thực hiện:

scala> val mymoo = new Foo.Moo(new Foo.Token) 
<console>:8: error: constructor Token in class Token cannot be accessed in objec 
t $iw 
     val mymoo = new Foo.Moo(new Foo.Token) 
         ^

Nhưng nếu khách hàng thực sự muốn để anh ấy có thể - không may - vẫn nhận được Moo của anh ấy:

val ireallywantone = new Foo.Moo(null.asInstanceOf[Foo.Token]) 
3

Tôi đoán nếu cả hai hàm tạo của Moo và phương thức boo đều nằm dưới sự kiểm soát của bạn và không cần phải được khách hàng viết thì bạn có thể thực hiện một tham số ẩn và sắp xếp nơi duy nhất giá trị tiềm ẩn phù hợp nằm trong phạm vi là boo.

Nó không lý tưởng ... và bạn không thể làm cho loại tham số ngầm hoàn toàn riêng tư (điều này sẽ làm cho nó chắc chắn hơn nhiều khi khách hàng không khởi tạo Moo bên ngoài boo), bởi vì Tôi nghi ngờ trình biên dịch sẽ phàn nàn về một loại tư nhân bị rò rỉ trong định nghĩa của Moo. Nhưng ngay cả khi không có điều đó, ít nhất cũng giúp bạn ngăn chặn vô tình tạo Moo bên ngoài boo; khách hàng sẽ phải cố tình có được một giá trị tiềm ẩn để cho phép họ tạo ra một Moo.

Các vấn đề liên quan