Dành cho các nhà khoa học và nhà phân tích dữ liệu quan tâm đến các phân tích có thể mở rộng được hỗ trợ bởi các thuật toán đồ thị và mô hình máy học
Thư viện GDS AuraDS
Neo4j Bloom và các công cụ khác
Hệ quản trị cơ sở dữ liệu Neo4j
Tìm hiểu cách khám phá biểu đồ của bạn với Neo4j Bloom và các công cụ khác, chẳng hạn như Neo4j Desktop, Neo4j Browser và Neo4j Ops Manager
công cụ neo4j
bảo mật neo4j
Tài liệu bảo mật
Đi thẳng vào phần bảo mật trong tài liệu sản phẩm của chúng tôi và tìm nội dung hữu ích khác liên quan đến bảo mật
Tài liệu bảo mật
Phiên bản cũ hơn và PDF
Tài liệu cho các bản phát hành trước đó có sẵn từ bộ chọn phiên bản trên mỗi trang. Để có danh sách đầy đủ, vui lòng xem kho lưu trữ Tài liệu của chúng tôi
Ngoài ra, hầu hết các tài liệu của chúng tôi đều có sẵn dưới dạng PDF có thể tải xuống. Để biết danh sách đầy đủ các tệp PDF có sẵn, hãy xem thư viện PDF
Phản ánh là khả năng của một chương trình để kiểm tra và thậm chí có thể tự sửa đổi. Nó có một lịch sử lâu dài trên các mô hình lập trình hướng đối tượng, chức năng và logic. Trong khi một số ngôn ngữ được xây dựng xung quanh sự phản ánh như một nguyên tắc hướng dẫn, nhiều ngôn ngữ dần dần phát triển khả năng phản ánh của chúng theo thời gian
Sự phản ánh liên quan đến khả năng cụ thể hóa [i. e. làm rõ ràng] các phần tử ngầm ẩn khác của một chương trình. Các phần tử này có thể là phần tử chương trình tĩnh như lớp, phương thức hoặc biểu thức hoặc phần tử động như sự kiện tiếp tục hoặc thực thi hiện tại, chẳng hạn như lời gọi phương thức và truy cập trường. Người ta thường phân biệt giữa phản ánh thời gian biên dịch và thời gian chạy tùy thuộc vào thời điểm quá trình phản chiếu được thực hiện. Phản ánh thời gian biên dịch là một cách mạnh mẽ để phát triển các trình biến đổi và trình tạo chương trình, trong khi phản ánh thời gian chạy thường được sử dụng để điều chỉnh ngữ nghĩa ngôn ngữ hoặc để hỗ trợ liên kết rất muộn giữa các thành phần phần mềm
Cho đến 2. 10, Scala không có bất kỳ khả năng phản chiếu nào của riêng nó. Thay vào đó, người ta có thể sử dụng một phần của API phản chiếu Java, cụ thể là xử lý việc cung cấp khả năng kiểm tra động các lớp và đối tượng và truy cập các thành viên của chúng. Tuy nhiên, nhiều phần tử dành riêng cho Scala không thể phục hồi dưới sự phản chiếu Java độc lập, chỉ hiển thị các phần tử Java [không có chức năng, không có đặc điểm] và các loại [không có loại tồn tại, loại cao hơn, phụ thuộc vào đường dẫn và loại trừu tượng]. Ngoài ra, phản ánh Java cũng không thể khôi phục thông tin loại thời gian chạy của các loại Java chung tại thời điểm biên dịch;
Trong Scala 2. Vào ngày 10 tháng 10, một thư viện phản chiếu mới đã được giới thiệu không chỉ để giải quyết những thiếu sót trong phản ánh thời gian chạy của Java đối với các loại chung và cụ thể của Scala, mà còn bổ sung một bộ công cụ mạnh mẽ hơn về các khả năng phản chiếu chung cho Scala. Cùng với phản ánh thời gian chạy đầy đủ tính năng cho các loại Scala và generic, Scala 2. 10 cũng có khả năng phản ánh thời gian biên dịch, ở dạng macro, cũng như khả năng thống nhất các biểu thức Scala thành các cây cú pháp trừu tượng
phản ánh thời gian chạy là gì?
- kiểm tra loại đối tượng đó, bao gồm các loại chung chung,
- để khởi tạo các đối tượng mới,
- hoặc để truy cập hoặc gọi các thành viên của đối tượng đó
Hãy bắt đầu và xem cách thực hiện từng điều trên với một vài ví dụ
ví dụ
Cũng như các ngôn ngữ JVM khác, các kiểu của Scala bị xóa tại thời điểm biên dịch. Điều này có nghĩa là nếu bạn kiểm tra loại thời gian chạy của một số phiên bản, thì bạn có thể không có quyền truy cập vào tất cả thông tin loại mà trình biên dịch Scala có sẵn tại thời điểm biên dịch
Các
6 có thể được coi là các đối tượng mang theo tất cả các loại thông tin có sẵn tại thời điểm biên dịch, thời gian chạy. Mặc dù vậy, điều quan trọng cần lưu ý là cácscala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
6 luôn được tạo bởi trình biên dịch. Quá trình tạo này được kích hoạt bất cứ khi nào một tham số ẩn hoặc ràng buộc ngữ cảnh yêu cầu sử dụngscala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
6. Điều này có nghĩa là, thông thường, người ta chỉ có thể nhận được mộtscala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
6 bằng cách sử dụng các tham số ẩn hoặc giới hạn ngữ cảnhscala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
Ví dụ: sử dụng giới hạn ngữ cảnh
scala> import scala.reflect.runtime.{universe => ru} import scala.reflect.runtime.{universe=>ru} scala> val l = List[1,2,3] l: List[Int] = List[1, 2, 3] scala> def getTypeTag[T: ru.TypeTag][obj: T] = ru.typeTag[T] getTypeTag: [T][obj: T][implicit evidence$1: ru.TypeTag[T]]ru.TypeTag[T] scala> val theType = getTypeTag[l].tpe theType: ru.Type = List[Int]
Ở phần trên, trước tiên chúng tôi nhập
0 [phải luôn nhập để sử dụng cácscala> case class Person[name: String] defined class Person scala> val m = ru.runtimeMirror[getClass.getClassLoader] m: scala.reflect.runtime.universe.Mirror = JavaMirror with ...
6] và chúng tôi tạo mộtscala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
2 có tên làscala> case class Person[name: String] defined class Person scala> val m = ru.runtimeMirror[getClass.getClassLoader] m: scala.reflect.runtime.universe.Mirror = JavaMirror with ...
3. Sau đó, chúng tôi xác định một phương thứcscala> case class Person[name: String] defined class Person scala> val m = ru.runtimeMirror[getClass.getClassLoader] m: scala.reflect.runtime.universe.Mirror = JavaMirror with ...
4 có tham số loạiscala> case class Person[name: String] defined class Person scala> val m = ru.runtimeMirror[getClass.getClassLoader] m: scala.reflect.runtime.universe.Mirror = JavaMirror with ...
5 có giới hạn ngữ cảnh [như REPL cho thấy, điều này tương đương với việc xác định tham số "bằng chứng" ngầm định, khiến trình biên dịch tạo ra mộtscala> case class Person[name: String] defined class Person scala> val m = ru.runtimeMirror[getClass.getClassLoader] m: scala.reflect.runtime.universe.Mirror = JavaMirror with ...
6 choscala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
5]. Cuối cùng, chúng tôi gọi phương thức của mình vớiscala> case class Person[name: String] defined class Person scala> val m = ru.runtimeMirror[getClass.getClassLoader] m: scala.reflect.runtime.universe.Mirror = JavaMirror with ...
3 dưới dạng tham số của nó và gọiscala> case class Person[name: String] defined class Person scala> val m = ru.runtimeMirror[getClass.getClassLoader] m: scala.reflect.runtime.universe.Mirror = JavaMirror with ...
9 trả về loại có trongscala> case class Person[name: String] defined class Person scala> val m = ru.runtimeMirror[getClass.getClassLoader] m: scala.reflect.runtime.universe.Mirror = JavaMirror with ...
6. Như chúng ta có thể thấy, chúng ta nhận được loại chính xác, đầy đủ [bao gồm cả đối số loại cụ thể củascala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
61],scala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
2scala> case class Person[name: String] defined class Person scala> val m = ru.runtimeMirror[getClass.getClassLoader] m: scala.reflect.runtime.universe.Mirror = JavaMirror with ...
Khi chúng tôi đã có được phiên bản
63 mong muốn, chúng tôi có thể kiểm tra nó, e. gscala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
scala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
Các loại thu được thông qua phản xạ có thể được khởi tạo bằng cách gọi hàm tạo của chúng bằng cách sử dụng một gương "gọi" thích hợp [các gương được mở rộng bên dưới]. Hãy xem qua một ví dụ sử dụng REPL
scala> case class Person[name: String] defined class Person scala> val m = ru.runtimeMirror[getClass.getClassLoader] m: scala.reflect.runtime.universe.Mirror = JavaMirror with ...
Trong bước đầu tiên, chúng tôi có được một bản sao
64 cung cấp tất cả các lớp và loại được tải bởi trình nạp lớp hiện tại, bao gồm cả lớpscala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
65scala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
6scala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
Bước thứ hai liên quan đến việc lấy một
66 cho lớpscala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
65 bằng cách sử dụng phương phápscala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
68.scala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
66 cung cấp quyền truy cập vào hàm tạo của lớpscala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
65. [Nếu bước này gây ra ngoại lệ, cách giải quyết dễ dàng là sử dụng các cờ này khi bắt đầu REPL.scala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
91]scala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
9scala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
Có thể lấy ký hiệu cho hàm tạo của
65 chỉ bằng cách sử dụng vũ trụ thời gian chạyscala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
93 bằng cách tra cứu nó trong các khai báo của loạiscala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
65scala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
4scala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
Truy cập và gọi các thành viên của các loại thời gian chạy
Nói chung, các thành viên của các loại thời gian chạy được truy cập bằng cách sử dụng máy nhân bản "người gọi" thích hợp [các máy nhân bản được mở rộng ở bên dưới]. Hãy xem qua một ví dụ sử dụng REPL
5scala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
Trong ví dụ này, chúng tôi sẽ cố gắng lấy và đặt trường
95 củascala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
96scala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
97, một cách phản ánhscala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
9scala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
Như chúng tôi đã làm trong ví dụ trước, chúng tôi sẽ bắt đầu bằng cách lấy một máy nhân bản
64, cung cấp tất cả các lớp và loại được tải bởi trình nạp lớp cũng đã tải lớpscala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
97 [scala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
96], mà chúng tôi cần để truy cập thành viênscala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
4scala> import scala.reflect.runtime.{universe => ru} import scala.reflect.runtime.{universe=>ru} scala> val l = List[1,2,3] l: List[Int] = List[1, 2, 3] scala> def getTypeTag[T: ru.TypeTag][obj: T] = ru.typeTag[T] getTypeTag: [T][obj: T][implicit evidence$1: ru.TypeTag[T]]ru.TypeTag[T] scala> val theType = getTypeTag[l].tpe theType: ru.Type = List[Int]
Bây giờ chúng ta tra cứu khai báo của trường
95, trường này cung cấp cho chúng ta mộtscala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
43 [một loại củascala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
44]. Chúng tôi sẽ cần sử dụngscala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
44 này sau để có được một bản sao cho phép chúng tôi truy cập vào giá trị của trường này [ví dụ: một số trường hợp]scala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
9scala> import scala.reflect.runtime.{universe => ru} import scala.reflect.runtime.{universe=>ru} scala> val l = List[1,2,3] l: List[Int] = List[1, 2, 3] scala> def getTypeTag[T: ru.TypeTag][obj: T] = ru.typeTag[T] getTypeTag: [T][obj: T][implicit evidence$1: ru.TypeTag[T]]ru.TypeTag[T] scala> val theType = getTypeTag[l].tpe theType: ru.Type = List[Int]
Để truy cập thành viên
95 của một phiên bản cụ thể, chúng tôi cần một máy nhân bản cho phiên bản cụ thể của chúng tôi, máy nhân bản củascala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
97,scala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
48. Với gương mẫu của chúng tôi, chúng tôi có thể nhận được mộtscala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
49 cho bất kỳscala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
43 nào đại diện cho một trường thuộc loại củascala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
97scala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
Bây giờ chúng ta có một
49 cho trường cụ thể của mình, chúng ta có thể sử dụng các phương phápscala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
53 vàscala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
54 để lấy/thiết lập thành viênscala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
95 của trường hợp cụ thể của chúng ta. Hãy thay đổi trạng thái củascala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
95 thànhscala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
57scala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
0scala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
Những người cảm thấy thoải mái khi sử dụng phản chiếu Java để lấy các thể hiện của Lớp Java trong thời gian chạy có thể nhận thấy rằng, trong Scala, thay vào đó, chúng tôi lấy các loại thời gian chạy
REPL-run dưới đây cho thấy một kịch bản rất đơn giản trong đó việc sử dụng phản chiếu Java trên các lớp Scala có thể trả về kết quả đáng ngạc nhiên hoặc không chính xác
Đầu tiên, chúng ta định nghĩa một lớp cơ sở
58 với một thành viên kiểu trừu tượng làscala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
5, và từ nó, chúng ta lấy được hai lớp con,scala> case class Person[name: String] defined class Person scala> val m = ru.runtimeMirror[getClass.getClassLoader] m: scala.reflect.runtime.universe.Mirror = JavaMirror with ...
90 vàscala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
91scala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
1scala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
Sau đó, chúng tôi tạo một thể hiện của cả
90 vàscala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
91, đồng thời tạo thành phần loạiscala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
5 cụ thể [trong cả hai trường hợp,scala> case class Person[name: String] defined class Person scala> val m = ru.runtimeMirror[getClass.getClassLoader] m: scala.reflect.runtime.universe.Mirror = JavaMirror with ...
95]scala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
2scala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
Bây giờ, chúng tôi sử dụng các phương thức
96 vàscala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
97 từ Java Reflection để lấy một thể hiện củascala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
98 đại diện cho các lớp thời gian chạy củascala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
99 vàscala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
40, sau đó chúng tôi kiểm tra xem lớp thời gian chạy củascala> import scala.reflect.runtime.{universe => ru} import scala.reflect.runtime.{universe=>ru} scala> val l = List[1,2,3] l: List[Int] = List[1, 2, 3] scala> def getTypeTag[T: ru.TypeTag][obj: T] = ru.typeTag[T] getTypeTag: [T][obj: T][implicit evidence$1: ru.TypeTag[T]]ru.TypeTag[T] scala> val theType = getTypeTag[l].tpe theType: ru.Type = List[Int]
40 có phải là một lớp con của lớp thời gian chạy củascala> import scala.reflect.runtime.{universe => ru} import scala.reflect.runtime.{universe=>ru} scala> val l = List[1,2,3] l: List[Int] = List[1, 2, 3] scala> def getTypeTag[T: ru.TypeTag][obj: T] = ru.typeTag[T] getTypeTag: [T][obj: T][implicit evidence$1: ru.TypeTag[T]]ru.TypeTag[T] scala> val theType = getTypeTag[l].tpe theType: ru.Type = List[Int]
99 khôngscala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
3scala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
Vì ở trên, chúng ta đã thấy rằng
91 mở rộng choscala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
90, kết quả này hơi bất ngờ. Khi thực hiện kiểm tra loại thời gian chạy đơn giản này, người ta sẽ mong đợi kết quả của câu hỏi “Lớpscala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
40 có phải là lớp con của lớpscala> import scala.reflect.runtime.{universe => ru} import scala.reflect.runtime.{universe=>ru} scala> val l = List[1,2,3] l: List[Int] = List[1, 2, 3] scala> def getTypeTag[T: ru.TypeTag][obj: T] = ru.typeTag[T] getTypeTag: [T][obj: T][implicit evidence$1: ru.TypeTag[T]]ru.TypeTag[T] scala> val theType = getTypeTag[l].tpe theType: ru.Type = List[Int]
99 không?” . Tuy nhiên, như bạn có thể nhận thấy ở trên, khiscala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
99 vàscala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
40 được khởi tạo, trình biên dịch Scala thực sự tạo ra các lớp con ẩn danh củascala> import scala.reflect.runtime.{universe => ru} import scala.reflect.runtime.{universe=>ru} scala> val l = List[1,2,3] l: List[Int] = List[1, 2, 3] scala> def getTypeTag[T: ru.TypeTag][obj: T] = ru.typeTag[T] getTypeTag: [T][obj: T][implicit evidence$1: ru.TypeTag[T]]ru.TypeTag[T] scala> val theType = getTypeTag[l].tpe theType: ru.Type = List[Int]
90 vàscala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
91, tương ứng. Điều này là do trình biên dịch Scala phải dịch Scala cụ thể [i. e. , không phải Java] thành một số tính năng tương đương trong mã byte Java để có thể chạy trên JVM. Do đó, trình biên dịch Scala thường tạo các lớp tổng hợp [i. e. các lớp được tạo tự động] được sử dụng trong thời gian chạy thay cho các lớp do người dùng định nghĩa. Điều này khá phổ biến trong Scala và có thể quan sát thấy khi sử dụng phản chiếu Java với một số tính năng của Scala, chẳng hạn như. g. bao đóng, loại thành viên, sàng lọc loại, lớp cục bộ, v.v.scala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
Trong những tình huống như thế này, thay vào đó, chúng ta có thể sử dụng phản xạ Scala để có được các loại thời gian chạy chính xác của các đối tượng Scala này. Các loại thời gian chạy Scala mang theo tất cả thông tin loại từ thời gian biên dịch, tránh các loại này không khớp giữa thời gian biên dịch và thời gian chạy
Dưới đây, chúng tôi xác định một phương thức sử dụng phản xạ Scala để lấy các kiểu thời gian chạy của các đối số của nó, sau đó kiểm tra mối quan hệ phân nhóm giữa hai. Nếu kiểu đối số đầu tiên của nó là kiểu con của kiểu đối số thứ hai, thì nó trả về
57scala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
4scala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
Như chúng ta có thể thấy, bây giờ chúng ta nhận được kết quả như mong đợi– Kiểu thời gian chạy của
40 thực sự là một kiểu con của kiểu thời gian chạy củascala> import scala.reflect.runtime.{universe => ru} import scala.reflect.runtime.{universe=>ru} scala> val l = List[1,2,3] l: List[Int] = List[1, 2, 3] scala> def getTypeTag[T: ru.TypeTag][obj: T] = ru.typeTag[T] getTypeTag: [T][obj: T][implicit evidence$1: ru.TypeTag[T]]ru.TypeTag[T] scala> val theType = getTypeTag[l].tpe theType: ru.Type = List[Int]
99scala> val decls = theType.decls.take[10] decls: Iterable[ru.Symbol] = List[constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++]
Phản xạ Scala cho phép một dạng siêu lập trình giúp các chương trình có thể tự sửa đổi tại thời điểm biên dịch. Phản ánh thời gian biên dịch này được thực hiện dưới dạng macro, cung cấp khả năng thực thi các phương thức thao tác với cây cú pháp trừu tượng tại thời điểm biên dịch
Một khía cạnh đặc biệt thú vị của macro là chúng dựa trên cùng một API cũng được sử dụng để phản ánh thời gian chạy của Scala, được cung cấp trong gói
95. Điều này cho phép chia sẻ mã chung giữa các macro và triển khai sử dụng phản ánh thời gian chạyscala> import scala.reflect.runtime.{universe => ru} import scala.reflect.runtime.{universe=>ru} scala> val l = List[1,2,3] l: List[Int] = List[1, 2, 3] scala> def getTypeTag[T: ru.TypeTag][obj: T] = ru.typeTag[T] getTypeTag: [T][obj: T][implicit evidence$1: ru.TypeTag[T]]ru.TypeTag[T] scala> val theType = getTypeTag[l].tpe theType: ru.Type = List[Int]
Lưu ý rằng hướng dẫn macro tập trung vào các chi tiết cụ thể của macro, trong khi hướng dẫn này tập trung vào các khía cạnh chung của API phản chiếu. Tuy nhiên, nhiều khái niệm áp dụng trực tiếp cho macro, chẳng hạn như cây cú pháp trừu tượng được thảo luận chi tiết hơn trong phần về Ký hiệu, Cây và Loại
Môi trường
Tất cả các nhiệm vụ phản ánh yêu cầu một môi trường thích hợp được thiết lập. Môi trường này khác nhau dựa trên việc tác vụ phản ánh sẽ được thực hiện trong thời gian chạy hay thời gian biên dịch. Sự khác biệt giữa một môi trường được sử dụng trong thời gian chạy hoặc thời gian biên dịch được gói gọn trong cái gọi là vũ trụ. Một khía cạnh quan trọng khác của môi trường phản chiếu là tập hợp các thực thể mà chúng ta có quyền truy cập phản chiếu vào. Tập hợp các thực thể này được xác định bởi cái gọi là gương
Các gương không chỉ xác định tập hợp các thực thể có thể được truy cập một cách phản chiếu. Họ cũng cung cấp các hoạt động phản ánh được thực hiện trên các thực thể đó. Ví dụ, trong phản ánh thời gian chạy, một gương phản chiếu có thể được sử dụng để gọi một phương thức hoặc hàm tạo của một lớp
vũ trụ
96 là điểm vào để phản ánh Scala. Một vũ trụ cung cấp một giao diện cho tất cả các khái niệm chính được sử dụng trong phản ánh, chẳng hạn nhưscala> import scala.reflect.runtime.{universe => ru} import scala.reflect.runtime.{universe=>ru} scala> val l = List[1,2,3] l: List[Int] = List[1, 2, 3] scala> def getTypeTag[T: ru.TypeTag][obj: T] = ru.typeTag[T] getTypeTag: [T][obj: T][implicit evidence$1: ru.TypeTag[T]]ru.TypeTag[T] scala> val theType = getTypeTag[l].tpe theType: ru.Type = List[Int]
97,scala> import scala.reflect.runtime.{universe => ru} import scala.reflect.runtime.{universe=>ru} scala> val l = List[1,2,3] l: List[Int] = List[1, 2, 3] scala> def getTypeTag[T: ru.TypeTag][obj: T] = ru.typeTag[T] getTypeTag: [T][obj: T][implicit evidence$1: ru.TypeTag[T]]ru.TypeTag[T] scala> val theType = getTypeTag[l].tpe theType: ru.Type = List[Int]
98 vàscala> import scala.reflect.runtime.{universe => ru} import scala.reflect.runtime.{universe=>ru} scala> val l = List[1,2,3] l: List[Int] = List[1, 2, 3] scala> def getTypeTag[T: ru.TypeTag][obj: T] = ru.typeTag[T] getTypeTag: [T][obj: T][implicit evidence$1: ru.TypeTag[T]]ru.TypeTag[T] scala> val theType = getTypeTag[l].tpe theType: ru.Type = List[Int]
99. Để biết thêm chi tiết, hãy xem phần của hướng dẫn này về Mirrors hoặc tài liệu API Mirrors trong góiscala> import scala.reflect.runtime.{universe => ru} import scala.reflect.runtime.{universe=>ru} scala> val l = List[1,2,3] l: List[Int] = List[1, 2, 3] scala> def getTypeTag[T: ru.TypeTag][obj: T] = ru.typeTag[T] getTypeTag: [T][obj: T][implicit evidence$1: ru.TypeTag[T]]ru.TypeTag[T] scala> val theType = getTypeTag[l].tpe theType: ru.Type = List[Int]
95scala> import scala.reflect.runtime.{universe => ru} import scala.reflect.runtime.{universe=>ru} scala> val l = List[1,2,3] l: List[Int] = List[1, 2, 3] scala> def getTypeTag[T: ru.TypeTag][obj: T] = ru.typeTag[T] getTypeTag: [T][obj: T][implicit evidence$1: ru.TypeTag[T]]ru.TypeTag[T] scala> val theType = getTypeTag[l].tpe theType: ru.Type = List[Int]