2015-08-18 12 views
6

Dường như tạo sự khác biệt cho dù bạn tham khảo this.type từ bên trong một Đặc điểm hoặc từ phạm vi nơi đối tượng được tạo, với kết quả đáng ngạc nhiên.Tương đương đáng ngạc nhiên và không tương đương về this.type

import scala.reflect.runtime.universe._ 

trait Trait { 
    val ttag = typeOf[this.type] 
    println(s"Trait constructor: $this") 
} 

object Instance1 extends Trait 

object Instance2 extends Trait 

println(typeOf[Instance1.type] =:= typeOf[Instance2.type]) // Should be false 
println(Instance1.ttag =:= Instance2.ttag)     // Should be false 
println(Instance1.ttag =:= typeOf[Instance1.type])   // Should be true 

Dưới đây là kết quả:

false // As expected: the singleton types of two objects are different. 
Trait constructor: [email protected] 
Trait constructor: [email protected] 
true  // But the this.type tags are equivalent 
false // and the this.type tag is not equivalent to the singleton type. 

Vì vậy, có hai đối tượng khác nhau, nhưng dường như mỗi ngày càng một thẻ loại tương đương cho this.type của nó, mà không phải là tương đương với .type của đối tượng như nhìn từ một phạm vi bao quanh.

Đây có phải là lỗi trình biên dịch hay không, nếu không, bạn có thể giải thích tại sao hành vi này có ý nghĩa không?

(Tôi đang chạy Scala 2.11.2. Tôi đã thử nó với một bí danh self cho this, với kết quả tương tự.)

+0

Vì những gì nó đáng giá chạy mã của bạn tôi nhận được một lỗi trình biên dịch nội bộ. Vì vậy, một lỗi trình biên dịch dường như không quá khó. Như một cách khác để thử nghiệm, một cách trực tiếp hơn để có được một ý tưởng tương tự là có một phương thức trả về kiểu của một đối tượng cục bộ. – Owen

+0

@Owen Dựa trên cuộc trò chuyện của chúng tôi bên dưới, tìm kiếm của tôi thông qua spec và tìm kiếm thông qua cơ sở dữ liệu vấn đề, tôi đã tiếp tục và đăng [lỗi Scala đầu tiên] (https://issues.scala-lang.org/browse/SI -9439) Tôi hy vọng nó không phải là một bản sao hoặc thực sự không phải là một lỗi! –

+0

Hiểu biết hiện tại của tôi (xây dựng từ nhận xét của Owen và Jason Zaugg): mỗi loại phụ thuộc vào đường dẫn có một “tiền tố” cho biết nơi tìm đối tượng trong phạm vi của nó. Loại kiểm tra tương đương nhìn vào tiền tố, không phải chính đối tượng (chỉ tồn tại ở thời gian chạy và có thể không bao giờ được tạo). Vì vậy, bên trong 'Trait',' this.type' có tiền tố 'Trait', dẫn đến kiểu' Trait.this.type' — cho tất cả các trường hợp. 'Instance1.type' có một tiền tố nói rằng đối tượng được định nghĩa trong phạm vi cấp cao nhất, với tên' Instance1', kết quả là kiểu 'Instance1.type' — khác với bên trong' Trait'. –

Trả lời

2

Các bản in chương trình sau đây sai và sau đó thành sự thật. Với tâm trí của tôi, không có sự khác biệt về vật chất giữa hai trường hợp này (mặc dù đó thực sự là một ý kiến ​​nhiều hơn; tôi không thể nói nếu có lý do hay không):

import scala.reflect.runtime.universe._ 

object Test2 extends App { 
    def foo(): Type = { 
    object a 
    typeOf[a.type] 
    } 

    println(foo() =:= foo()) // false 

    trait Trait { 
    val ttag = typeOf[this.type] 
    } 

    object Instance1 extends Trait 

    object Instance2 extends Trait 

    println(Instance1.ttag =:= Instance2.ttag) // true 
} 
+0

Tôi nghĩ rằng kể từ khi hai đối tượng được tạo ra bởi các cuộc gọi đến 'foo' là khác nhau, đó là chính xác rằng các loại thẻ đơn kiểu của họ là khác nhau. Tạo một đối tượng vi phạm tính minh bạch tham chiếu — hoặc thực hiện nó? Có lẽ đây là chìa khóa cho những gì tôi hỏi. –

+0

[spec nói] (http://www.scala-lang.org/files/archive/spec/2.11/05-classes-and-objects.html#object-definitions) rằng định nghĩa đối tượng xác định một đối tượng duy nhất của một _new class._ Cho đến nay, tôi đã không tìm thấy bất cứ điều gì để chỉ ra cho dù một định nghĩa đối tượng duy nhất bên trong một định nghĩa chức năng nên xác định một đối tượng hoặc nhiều đối tượng như lần chức năng được gọi. Nhưng nó xuất hiện rằng hai 'Instance ', có định nghĩa riêng biệt, nên có các loại riêng biệt. –

+0

@BenKovitz Truyền '-Yprint: typer' có thể là thông tin ở đây ... nó sẽ desugar định nghĩa đối tượng vào một định nghĩa lớp và tạo một cá thể mới, vì vậy bạn có thể thấy chính xác có bao nhiêu trường hợp được tạo. – Owen