Dynamic Features
Inspect one language lane at a time so line-level text and code deltas stay readable.
Diff Lane
English
0 modified sections0 code block delta0 anchor delta
Diff Lane
中文
3 modified sections0 code block delta0 anchor delta
modified仓颉反射基本介绍text+1 line, -1 line
v1.0.5
Section Text
1
反射指程序可以访问、检测和修改它本身状态或行为的一种机制。2
3
反射这一动态特性有以下的优点:4
5
- 提高了程序的灵活性和扩展性。6
7
- 程序能够在运行时获悉各种对象的类型,对其成员进行枚举、调用等操作。8
9
- 允许在运行时创建新类型,无需提前硬编码。10
11
但使用反射调用,其性能通常低于直接调用,因此反射机制主要应用于对灵活性和拓展性要求很高的系统框架上。v1.1.0
Section Text
1
反射指程序可以访问、检测和修改它本身状态或行为的一种机制。2
3
反射这一动态特性有以下的优点:4
5
- 提高了程序的灵活性和扩展性。6
7
- 程序能够在运行时获悉各种对象的类型,对其成员进行枚举、调用等操作。8
9
- 允许在运行时创建新类型,无需提前硬编码。10
11
但使用反射调用,其性能通常低于直接调用,因此反射机制主要应用于对灵活性和扩展性要求很高的系统框架上。modified如何获得 TypeInfotextcode+4 lines, -1 line
v1.0.5
Section Text
1
对于仓颉的反射特性,需要知道 TypeInfo 这一类型,这个核心类型中记录任意类型的类型信息,并且定义了方法用于获取类型信息、设置值等。当然为了便于用户操作仓颉还提供了 ClassTypeInfo、PrimitiveTypeInfo、ParameterInfo 等一系列的信息类型。2
3
可以使用三种静态的 `of` 方法来生成 TypeInfo 信息类。4
5
6
当采用入参为 `Any` 和 `Object` 类型的 `of` 函数,输出为该实例的运行时类型信息,采用泛型参数的 `of` 函数则会返回传入参数的静态类型信息。两种方法产生的信息完全相同,但不保证一定对应同一对象。7
8
例如可以用反射来获取一个自定义类型的类型信息。9
10
11
编译并执行上面的代码,会输出:12
13
14
此外 TypeInfo 还提供了静态函数 `get`,该接口可通过传入的类型名称获取 TypeInfo。15
16
17
请注意,传入参数需要符合 `module.package.type` 的完全限定模式规则。对于编译器预导入的类型,包含 core 包中的类型和编译器内置类型,例如 `primitive type`、`Option`、`Iterable` 等,查找的字符串需要直接使用其类型名,不能带包名和模块名前缀。当运行时无法查询到对应类型的实例,则会抛出 `InfoNotFoundException`。18
19
20
采用这种方式时无法获取一个未实例化的泛型类型。Code 1 · cangjie
1
public class TypeInfo {2
public static func of(a: Any): TypeInfo3
public static func of(a: Object): ClassTypeInfo4
public static func of<T>(): TypeInfo5
}Code 2 · cangjie
1
import std.reflect.*2
3
class Foo {}4
5
main() {6
let a: Foo = Foo()7
let info: TypeInfo = TypeInfo.of(a)8
let info2: TypeInfo = TypeInfo.of<Foo>()9
println(info)10
println(info2)11
}Code 3 · text
1
default.Foo2
default.FooCode 4 · cangjie
1
public class TypeInfo {2
public static func get(qualifiedName: String): TypeInfo3
}Code 5 · cangjie
1
let t1: TypeInfo = TypeInfo.get("Int64")2
let t1: TypeInfo = TypeInfo.get("default.Foo")3
let t2: TypeInfo = TypeInfo.get("std.socket.TcpSocket")4
let t3: TypeInfo = TypeInfo.get("net.http.ServerBuilder")Code 6 · cangjie
1
import std.collection.*2
import std.reflect.*3
4
class A<T> {5
A(public let t: T) {}6
}7
8
class B<T> {9
B(public let t: T) {}10
}11
12
main() {13
let aInfo: TypeInfo = TypeInfo.get("default.A<Int64>")// Error,`default.A<Int64>` is not instantiated,will throw InfoNotFoundException14
let b: B<Int64> = B<Int64>(1)15
let bInfo: TypeInfo = TypeInfo.get("default.B<Int64>")// OK `default.B<Int64>` has been instantiated.16
}v1.1.0
Section Text
1
对于仓颉的反射特性,需要知道 TypeInfo 这一类型,这个核心类型中记录任意类型的类型信息,并且定义了方法用于获取类型信息、设置值等。当然为了便于用户操作仓颉还提供了 ClassTypeInfo、PrimitiveTypeInfo、ParameterInfo 等一系列的信息类型。2
3
可以使用三种静态的 `of` 方法来生成 TypeInfo 信息类。4
5
<!-- code_no_check -->6
7
当采用入参为 `Any` 和 `Object` 类型的 `of` 函数,输出为该实例的运行时类型信息,采用泛型参数的 `of` 函数则会返回传入参数的静态类型信息。两种方法产生的信息完全相同,但不保证一定对应同一对象。8
9
例如可以用反射来获取一个自定义类型的类型信息。10
11
<!-- verify -->12
13
14
编译并执行上面的代码,会输出:15
16
17
此外 TypeInfo 还提供了静态函数 `get`,该接口可通过传入的类型名称获取 TypeInfo。18
19
<!-- code_no_check -->20
21
请注意,传入参数需要符合 `module.package.type` 的完全限定模式规则。对于编译器预导入的类型,包含 core 包中的类型和编译器内置类型,例如 `primitive type`、`Option`、`Iterable` 等,查找的字符串需要直接使用其类型名,不能带包名和模块名前缀。当运行时无法查询到对应类型的实例,则会抛出 `InfoNotFoundException`。22
23
示例:(会运行报错)24
25
<!-- run.error -->Code 1 · cangjie
1
public class TypeInfo {2
public static func of(a: Any): TypeInfo3
public static func of(a: Object): ClassTypeInfo4
public static func of<T>(): TypeInfo5
}Code 2 · cangjie
1
import std.reflect.*2
3
class Foo {}4
5
main() {6
let a: Foo = Foo()7
let info: TypeInfo = TypeInfo.of(a)8
let info2: TypeInfo = TypeInfo.of<Foo>()9
println(info)10
println(info2)11
}Code 3 · text
1
default.Foo2
default.FooCode 4 · cangjie
1
public class TypeInfo {2
public static func get(qualifiedName: String): TypeInfo3
}Code 5 · cangjie
1
import std.reflect.*2
3
main() {4
let t1: TypeInfo = TypeInfo.get("default.Foo")5
}Code 6 · cangjie
1
modified如何使用反射访问成员textcode+1 line
v1.0.5
Section Text
1
在获取到对应的类型信息类即 `TypeInfo` 后,便可以通过其相应接口访问对应类的实例成员以及静态成员。此外 `TypeInfo` 的子类 `ClassTypeInfo` 还提供了接口用于访问类公开的构造函数以及它的成员变量、属性、函数。仓颉的反射被设计为只能访问到类型内 public 的成员,意味着 private 和 protected 修饰的成员在反射中是不可见的。2
3
例如当想要在运行时对类的某一实例成员变量进行获取与修改。4
5
6
编译并执行上面的代码,会输出:7
8
9
同时也可以通过反射对属性进行检查以及修改。10
11
12
编译并执行上面的代码,会输出:13
14
15
还可以通过反射机制进行函数调用。16
17
18
编译并执行上面的代码,会输出:Code 1 · cangjie
1
import std.reflect.*2
3
public class Foo {4
public static var param1 = 205
public var param2 = 106
}7
8
main(): Unit{9
let obj = Foo()10
let info = TypeInfo.of(obj)11
let staticVarInfo = info.getStaticVariable("param1")12
let instanceVarInfo = info.getInstanceVariable("param2")13
println("成员变量初始值")14
print("Foo 的静态成员变量 ${staticVarInfo} = ")15
println((staticVarInfo.getValue() as Int64).getOrThrow())16
print("obj 的实例成员变量 ${instanceVarInfo} = ")17
println((instanceVarInfo.getValue(obj) as Int64).getOrThrow())18
println("更改成员变量")19
staticVarInfo.setValue(8)20
instanceVarInfo.setValue(obj, 25)21
print("Foo 的静态成员变量 ${staticVarInfo} = ")22
println((staticVarInfo.getValue() as Int64).getOrThrow())23
print("obj 的实例成员变量 ${instanceVarInfo} = ")24
println((instanceVarInfo.getValue(obj) as Int64).getOrThrow())25
return26
}Code 2 · text
1
成员变量初始值2
Foo 的静态成员变量 static param1: Int64 = 203
obj 的实例成员变量 param2: Int64 = 104
更改成员变量5
Foo 的静态成员变量 static param1: Int64 = 86
obj 的实例成员变量 param2: Int64 = 25Code 3 · cangjie
1
import std.reflect.*2
3
public class Foo {4
public let _p1: Int64 = 15
public prop p1: Int64 {6
get() { _p1 }7
}8
public var _p2: Int64 = 29
public mut prop p2: Int64 {10
get() { _p2 }11
set(v) { _p2 = v }12
}13
}14
15
main(): Unit{16
let obj = Foo()17
let info = TypeInfo.of(obj)18
let instanceProps = info.instanceProperties.toArray()19
println("obj的实例成员属性包含${instanceProps}")20
let PropInfo1 = info.getInstanceProperty("p1")21
let PropInfo2 = info.getInstanceProperty("p2")22
23
println((PropInfo1.getValue(obj) as Int64).getOrThrow())24
println((PropInfo2.getValue(obj) as Int64).getOrThrow())25
if (PropInfo1.isMutable()) {26
PropInfo1.setValue(obj, 10)27
}28
if (PropInfo2.isMutable()) {29
PropInfo2.setValue(obj, 20)30
}31
println((PropInfo1.getValue(obj) as Int64).getOrThrow())32
println((PropInfo2.getValue(obj) as Int64).getOrThrow())33
return34
}Code 4 · text
1
obj 的实例成员属性包含[prop p1: Int64, mut prop p2: Int64]2
13
24
15
20Code 5 · cangjie
1
import std.reflect.*2
3
public class Foo {4
public static func f1(v0: Int64, v1: Int64): Int64 {5
return v0 + v16
}7
}8
9
main(): Unit {10
var num = 011
let intInfo = TypeInfo.of<Int64>()12
let funcInfo = TypeInfo.of<Foo>().getStaticFunction("f1", intInfo, intInfo)13
num = (funcInfo.apply(TypeInfo.of<Foo>(), [1, 1]) as Int64).getOrThrow()14
println(num)15
}Code 6 · text
1
2v1.1.0
Section Text
1
在获取到对应的类型信息类即 `TypeInfo` 后,便可以通过其相应接口访问对应类的实例成员以及静态成员。此外 `TypeInfo` 的子类 `ClassTypeInfo` 还提供了接口用于访问类公开的构造函数以及它的成员变量、属性、函数。仓颉的反射被设计为只能访问到类型内 public 的成员,意味着 private 和 protected 修饰的成员在反射中是不可见的。2
3
例如当想要在运行时对类的某一实例成员变量进行获取与修改。4
5
<!-- verify -->6
7
8
编译并执行上面的代码,会输出:9
10
11
同时也可以通过反射对属性进行检查以及修改。12
13
<!-- verify -->14
15
16
编译并执行上面的代码,会输出:17
18
19
还可以通过反射机制进行函数调用。20
21
<!-- verify -->22
23
24
编译并执行上面的代码,会输出:Code 1 · cangjie
1
import std.reflect.*2
3
public class Foo {4
public static var param1 = 205
public var param2 = 106
}7
8
main(): Unit {9
let obj = Foo()10
let info = TypeInfo.of(obj)11
let staticVarInfo = info.getStaticVariable("param1")12
let instanceVarInfo = info.getInstanceVariable("param2")13
println("成员变量初始值")14
print("Foo 的静态成员变量 ${staticVarInfo} = ")15
println((staticVarInfo.getValue() as Int64).getOrThrow())16
print("obj 的实例成员变量 ${instanceVarInfo} = ")17
println((instanceVarInfo.getValue(obj) as Int64).getOrThrow())18
println("更改成员变量")19
staticVarInfo.setValue(8)20
instanceVarInfo.setValue(obj, 25)21
print("Foo 的静态成员变量 ${staticVarInfo} = ")22
println((staticVarInfo.getValue() as Int64).getOrThrow())23
print("obj 的实例成员变量 ${instanceVarInfo} = ")24
println((instanceVarInfo.getValue(obj) as Int64).getOrThrow())25
return26
}Code 2 · text
1
成员变量初始值2
Foo 的静态成员变量 static param1: Int64 = 203
obj 的实例成员变量 param2: Int64 = 104
更改成员变量5
Foo 的静态成员变量 static param1: Int64 = 86
obj 的实例成员变量 param2: Int64 = 25Code 3 · cangjie
1
import std.reflect.*2
3
public class Foo {4
public let _p1: Int64 = 15
public prop p1: Int64 {6
get() { _p1 }7
}8
public var _p2: Int64 = 29
public mut prop p2: Int64 {10
get() { _p2 }11
set(v) { _p2 = v }12
}13
}14
15
main(): Unit {16
let obj = Foo()17
let info = TypeInfo.of(obj)18
let instanceProps = info.instanceProperties.toArray()19
println("obj的实例成员属性包含${instanceProps}")20
let PropInfo1 = info.getInstanceProperty("p1")21
let PropInfo2 = info.getInstanceProperty("p2")22
23
println((PropInfo1.getValue(obj) as Int64).getOrThrow())24
println((PropInfo2.getValue(obj) as Int64).getOrThrow())25
if (PropInfo1.isMutable()) {26
PropInfo1.setValue(obj, 10)27
}28
if (PropInfo2.isMutable()) {29
PropInfo2.setValue(obj, 20)30
}31
println((PropInfo1.getValue(obj) as Int64).getOrThrow())32
println((PropInfo2.getValue(obj) as Int64).getOrThrow())33
return34
}Code 4 · text
1
obj 的实例成员属性包含[prop p1: Int64, mut prop p2: Int64]2
13
24
15
20Code 5 · cangjie
1
import std.reflect.*2
3
public class Foo {4
public static func f1(v0: Int64, v1: Int64): Int64 {5
return v0 + v16
}7
}8
9
main(): Unit {10
var num = 011
let intInfo = TypeInfo.of<Int64>()12
let funcInfo = TypeInfo.of<Foo>().getStaticFunction("f1", intInfo, intInfo)13
num = (funcInfo.apply(TypeInfo.of<Foo>(), [1, 1]) as Int64).getOrThrow()14
println(num)15
}Code 6 · text
1
2