2015-03-18 20 views
5

Làm cách nào để biết hai đối tượng của lớp bên trong có cùng loại thời gian chạy không? Trong ví dụ dưới đây, tôi mong đợi để xem lớp aa.getClass == a.Inner và ba.getClass == b.Inner, nhưng trên thực tế chúng là cả hai Outer.Inner và bằng nhau.scala: so sánh các loại đối tượng lớp bên trong

class Outer{ 
     class Inner{} 
    } 

    val a = new Outer 
    val b = new Outer 

    val aa = new a.Inner 
    val ab = new a.Inner 
    val ba = new b.Inner 

    val res1 = aa.getClass == ba.getClass 
    val res2 = aa.isInstanceOf[ab.type ] 

    scala>  |  | defined class Outer 

    scala> a: Outer = [email protected] 

    scala> b: Outer = [email protected] 

    scala> aa: a.Inner = [email protected] 

    scala> ab: a.Inner = [email protected] 

    scala> ba: b.Inner = [email protected] 

    scala> res1: Boolean = true 

    scala> res2: Boolean = false 

Trả lời

5

... aa.getClass == a.Inner và ba.getClass == b.Inner, nhưng trên thực tế họ đều Outer.Inner và bình đẳng

Đây không phải là thật. Inner là thành viên của lớp học và là duy nhất đối với phiên bản gốc của nó của Outer. Điều này có nghĩa là cả hai ab đều có phiên bản Inner độc đáo của riêng chúng, đây là các loại không tương thích. Vì vậy, a.Innerkhông phải cùng loại với b.Inner và do đó, a.Inner không bao giờ có thể bằng b.Inner. Tôi không thể chỉ định một cho người khác:

scala> val z: a.Inner = aa  // aa is a.Inner, so this is ok 
z: a.Inner = [email protected] 

scala> val z: b.Inner = aa  // aa is not b.Inner, so it fails to compile 
<console>:14: error: type mismatch; 
found : a.Inner 
required: b.Inner 
     val z: b.Inner = aa 
         ^

getClass không phải là rất hữu ích ở đây.

Chúng ta có thể chứng minh điều này với sự phản ánh:

import scala.reflect.runtime.universe._ 

def tpeOf[A](a: A)(implicit tt: TypeTag[A]) = tt.tpe 

scala> tpeOf(aa) =:= tpeOf(ba) // different Outer parents 
res24: Boolean = false 

scala> tpeOf(aa) =:= tpeOf(aa) // Same instance 
res25: Boolean = true 

scala> tpeOf(aa) =:= tpeOf(ab) // Same Outer parent 
res26: Boolean = true 

Mặt khác, bạn có thể sử dụng Outer#Inner để xác định rằng bạn không quan tâm mà Outer loại Inner của bạn thuộc về.

val x: Outer#Inner = aa 
val x: Outer#Inner = ab 
val x: Outer#Inner = ba 

Vì vậy, như đã nêu bởi @BenReich, bạn có thể sử dụng aa.isInstanceOf[Outer#Inner] để kiểm tra xem bạn có bất kỳ các loại, và tất cả họ sẽ quay trở lại true.

ab.type có nghĩa là một cái gì đó hoàn toàn khác. ab.type là loại đơn lẻ không chứa gì ngoài số ab. Vì vậy, tự nhiên sau đó, aa.isInstanceOf[ab.type] phải là sai, bởi vì aa không phải là ab, bất kể chúng có phải là cả hai a.Inner.

+0

Có thể đáng nói rằng cả hai đều có thể gán cho 'Outer # Inner' –

+0

Cảm ơn! Thật lạ khi chúng ta cần viết một phương thức tùy chỉnh để sử dụng khi so sánh các đối tượng lớp bên trong ... – Yegor

+0

@Yegor Lưu ý rằng bạn * có thể * làm 'ab.isInstanceOf [Outer # Inner]' với hiệu ứng mong muốn. –

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