Tôi muốn lấy kiểu biến trong thời gian chạy. Làm cách nào để thực hiện việc này?Tôi muốn lấy kiểu biến tại thời gian chạy
Trả lời
vì vậy, nói đúng, "loại của một biến "luôn luôn hiện diện, và có thể được truyền xung quanh như một tham số kiểu. Ví dụ:
val x = 5
def f[T](v: T) = v
f(x) // T is Int, the type of x
Nhưng tùy thuộc vào những gì bạn muốn làm , điều đó sẽ không giúp bạn. Ví dụ, có thể muốn không biết loại của biến là gì, nhưng biết nếu loại của giá trị là một số loại hình cụ thể, chẳng hạn như thế này:
val x: Any = 5
def f[T](v: T) = v match {
case _: Int => "Int"
case _: String => "String"
case _ => "Unknown"
}
f(x)
Ở đây nó không có vấn đề gì là loại biến, Any
. Những gì quan trọng, những gì được kiểm tra là loại 5
, giá trị. Thực tế, T
là vô ích - bạn có thể đã viết nó def f(v: Any)
thay thế. Ngoài ra, điều này sử dụng hoặc là ClassTag
hoặc giá trị Class
, được giải thích bên dưới và không thể kiểm tra thông số loại của một loại: bạn có thể kiểm tra xem có gì đó là List[_]
(List
của một thứ gì đó), nhưng không List[Int]
hoặc List[String]
.
Một khả năng khác là bạn muốn chỉnh sửa loại biến. Tức là, bạn muốn chuyển đổi loại thành một giá trị, vì vậy bạn có thể lưu trữ nó, vượt qua nó, vv Điều này liên quan đến sự phản ánh, và bạn sẽ sử dụng hoặc ClassTag
hoặc TypeTag
. Ví dụ:
val x: Any = 5
import scala.reflect.ClassTag
def f[T](v: T)(implicit ev: ClassTag[T]) = ev.toString
f(x) // returns the string "Any"
A ClassTag
cũng sẽ cho phép bạn sử dụng thông số loại bạn nhận được trên match
.Điều này sẽ không làm việc:
def f[A, B](a: A, b: B) = a match {
case _: B => "A is a B"
case _ => "A is not a B"
}
Nhưng điều này sẽ:
val x = 'c'
val y = 5
val z: Any = 5
import scala.reflect.ClassTag
def f[A, B: ClassTag](a: A, b: B) = a match {
case _: B => "A is a B"
case _ => "A is not a B"
}
f(x, y) // A (Char) is not a B (Int)
f(x, z) // A (Char) is a B (Any)
Ở đây tôi đang sử dụng bối cảnh tiếp giáp cú pháp, B : ClassTag
, mà hoạt động giống như các tham số ngầm định trong hợp ClassTag
ví dụ trước , nhưng sử dụng biến ẩn danh.
Người ta cũng có thể nhận được một ClassTag
từ một giá trị của Class
, như thế này:
val x: Any = 5
val y = 5
import scala.reflect.ClassTag
def f(a: Any, b: Any) = {
val B = ClassTag(b.getClass)
ClassTag(a.getClass) match {
case B => "a is the same class as b"
case _ => "a is not the same class as b"
}
}
f(x, y) == f(y, x) // true, a is the same class as b
Một ClassTag
được giới hạn ở chỗ nó chỉ bao gồm các lớp cơ sở, nhưng không tham số kiểu của nó. Tức là, ClassTag
cho List[Int]
và List[String]
giống nhau, List
. Nếu bạn cần thông số loại, thì bạn phải sử dụng một số TypeTag
thay thế. Tuy nhiên, không thể lấy giá trị TypeTag
từ giá trị, cũng như không thể sử dụng trên kết hợp mẫu, do xóa của JVM.
Ví dụ với TypeTag
có thể nhận được khá phức tạp - thậm chí không so sánh hai loại thẻ là không chính xác đơn giản, như có thể thấy dưới đây:
import scala.reflect.runtime.universe.TypeTag
def f[A, B](a: A, b: B)(implicit evA: TypeTag[A], evB: TypeTag[B]) = evA == evB
type X = Int
val x: X = 5
val y = 5
f(x, y) // false, X is not the same type as Int
Tất nhiên, có nhiều cách để thực hiện so sánh mà trở thành sự thật, nhưng nó sẽ yêu cầu một vài chương sách thực sự bao gồm TypeTag
, vì vậy tôi sẽ dừng lại ở đây.
Cuối cùng, có thể bạn không quan tâm đến loại biến nào cả. Có lẽ bạn chỉ muốn biết lớp của một giá trị, trong trường hợp câu trả lời là khá đơn giản là những gì:
val x = 5
x.getClass // int -- technically, an Int cannot be a class, but Scala fakes it
Sẽ tốt hơn, tuy nhiên, để cụ thể hơn về những gì bạn muốn đạt được, do đó câu trả lời có thể được thêm vào vấn đề.
Nếu bằng loại biến bạn có nghĩa là lớp thời gian chạy của đối tượng mà biến trỏ đến, thì bạn có thể nhận được điều này thông qua tham chiếu lớp mà tất cả các đối tượng đều có.
val name = "sam";
name: java.lang.String = sam
name.getClass
res0: java.lang.Class[_] = class java.lang.String
Nếu bạn có nghĩa là loại biến được khai báo là, thì bạn không thể nhận được biến đó. Ví dụ: nếu bạn nói
val name: Object = "sam"
thì bạn vẫn sẽ nhận được String
trở lại từ mã trên.
Bạn cũng có thể làm 'name.getClass.getSimpleName' cho một đầu ra dễ đọc hơn –
Tôi nghĩ câu hỏi chưa hoàn chỉnh. nếu bạn có nghĩa là bạn muốn để có được các loại thông tin của một số typeclass sau đó dưới đây:
Nếu bạn muốn in như bạn đã xác định rồi:
scala> def manOf[T: Manifest](t: T): Manifest[T] = manifest[T]
manOf: [T](t: T)(implicit evidence$1: Manifest[T])Manifest[T]
scala> val x = List(1,2,3)
x: List[Int] = List(1, 2, 3)
scala> println(manOf(x))
scala.collection.immutable.List[Int]
Nếu bạn đang ở trong chế độ repl sau đó
scala> :type List(1,2,3)
List[Int]
Hoặc nếu bạn chỉ muốn biết những gì lớp gõ sau đó là @monkjack giải thích "string".getClass
có thể giải quyết mục đích
tôi đã thử nghiệm điều đó và nó làm việc
val x = 9
def printType[T](x:T) :Unit = {println(x.getClass.toString())}
- 1. Biến số SSIS tại thời gian chạy
- 2. Tại sao tôi không thể thay đổi biến long_query_time biến tại thời gian chạy
- 3. Biến typelist có chức năng tại thời gian chạy
- 4. Cách lấy nội dung/loại tệp tại thời gian chạy
- 5. Truy xuất kiểu thời gian chạy VB6
- 6. Làm thế nào tôi có thể theo dõi một biến tại thời gian chạy trong C#?
- 7. Cách lấy thời gian hiện tại
- 8. Thay thế đậu tại thời gian chạy
- 9. Thay đổi menu tại thời gian chạy
- 10. Ràng buộc Ninject tại thời gian chạy
- 11. Chạy PublicResXFileCodeGenerator tại thời gian biên dịch
- 12. Thay đổi App.config tại Thời gian chạy
- 13. phương thức gọi tại thời gian chạy
- 14. Luigi - Unfulfilled% s tại thời gian chạy
- 15. Sửa đổi Vtable tại thời gian chạy
- 16. Lấy tên biến cục bộ (và tham số) tại thời gian chạy thông qua biểu thức lambda
- 17. Có thể xem các biến trong thời gian chạy không?
- 18. Lấy thời gian từ Biến DateTime trong Ruby
- 19. Tạo danh sách <> từ kiểu thời gian chạy
- 20. C# Loại đúc tại thời gian chạy Sử dụng Reflection
- 21. Drools lấy dữ kiện từ cơ sở dữ liệu tại thời gian chạy
- 22. Vimscript: cách lấy kiểu tệp hiện tại dưới dạng biến
- 23. Thêm chú thích Java tại thời gian chạy
- 24. Lấy các tập hợp thời gian chạy trong Silverlight 3
- 25. Tạo Kiểu Chung với Giao diện Chung tại Thời gian Chạy
- 26. Gọi hàm chung với tham số kiểu được xác định tại thời gian chạy
- 27. & phím nóng không biến mất trong thời gian chạy
- 28. cách xem giá trị của các biến tĩnh tại thời gian chạy trong studio trực quan
- 29. Thời gian chạy biến của chương trình C
- 30. eval() không gán biến trong thời gian chạy
Đoạn mã ví dụ bạn đã viết sau khi "Nhưng điều này sẽ:" là khó hiểu. Nó biên dịch nhưng kết quả không phải là kết quả bạn hiển thị trong phần bình luận. Cả hai cuộc gọi đều trả về cùng một kết quả: "A là B". Bởi vì giá trị '5' là cả một thể hiện của' Int' và một thể hiện của 'Bất kỳ'. Ngoài ra, lời giải thích của bạn là hoàn hảo :) – Readren
@Readren Giá trị không được kiểm tra, lớp đó là. 'Int' là' Any', nhưng 'Bất kỳ' không phải là' Int'. Nó hoạt động trên Scala 2.10, và nó _should_ làm việc trên Scala 2.11, và tôi không biết tại sao nó không phải là. –
Nó làm tôi sợ mâu thuẫn với một eminence như bạn, nhưng mã 'a match {case _: B => ...' kiểm tra kiểu giá trị thực của biến 'a', không phải kiểu biến' a' '. Bạn có quyền trả lời những gì bạn nói trong scala 2.10.6. Nhưng nó phải là một lỗi. Trong scala 2.11.8 loại giá trị thực tế được kiểm tra, như nó cần. – Readren