Access Rules
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
中文
1 modified sections0 code block delta0 anchor delta
modified扩展的导入导出text+4 lines
v1.0.5
Section Text
1
扩展也是可以被导入和导出的,但是扩展本身不能使用可见性修饰符修饰,扩展的导出有一套特殊的规则。2
3
对于直接扩展,当扩展与被扩展的类型在同一个包中,扩展是否导出,由被扩展类型与泛型约束(如果有)的访问修饰符同时决定,当所有的泛型约束都是导出类型(修饰符与导出规则,详见[顶层声明的可见性](../package/toplevel_access.md)章节)时,该扩展将被导出。当扩展与被扩展类型不在同一个包中时,该扩展不会导出。4
5
如以下代码所示,`Foo` 是导出的,`f1` 函数所在的扩展由于不导出泛型约束,故该扩展不会被导出;`f2` 和 `f3` 函数所在的扩展的泛型约束均被导出,故该扩展被导出;`f4` 函数所在的扩展包含多个泛型约束,且泛型约束中 `I1` 未被导出,故该扩展不会被导出;`f5` 函数所在的扩展包含多个泛型约束,所有的泛型约束均是导出的,故该扩展会被导出。6
7
8
对于接口扩展则分为两种情况:9
10
1. 当接口扩展与被扩展类型在相同的 `package` 时,扩展会与被扩展类型以及泛型约束(如果有)一起被导出,不受接口类型的访问级别影响,包外不需要导入接口类型也能访问该扩展的成员。11
2. 当接口扩展与被扩展类型在不同的 `package` 时,接口扩展是否导出由接口类型以及泛型约束(如果有)里用到的类型中最小的访问级别决定。其他 `package` 必须导入被扩展类型、相应的接口以及约束用到的类型(如果有),才能访问对应接口包含的扩展成员。12
13
如下代码所示,在包 `a` 中,虽然接口访问修饰符为 `private`,但 `Foo` 的扩展仍然会被导出。14
15
16
当在其他包中为 `Foo` 类型扩展时,扩展是否导出由实现接口和泛型约束的访问修饰符决定。实现接口至少存在一个导出的接口,且所有的泛型约束均可导出时,该扩展将被导出。17
18
19
特别的,接口扩展导出的成员仅限于接口中包含的成员。20
21
<!-- compile.error -access_rules3 -->22
<!-- cfg="-p a --output-type=staticlib" -->23
24
25
<!-- compile.error -access_rules3 -->26
<!-- cfg="-p b --output-type=staticlib" -->27
28
29
<!-- compile.error -access_rules3 -->30
<!-- cfg="-p c --output-type=staticlib" -->31
<!-- cfg="liba.a libb.a" -->32
33
34
与扩展的导出类似,扩展的导入也不需要显式地用 `import` 导入,扩展的导入只需要导入被扩展的类型、接口和泛型约束,就可以导入可访问的所有扩展。35
36
如下面的代码所示,在 `package b` 中,只需要导入 `Foo` 就可以使用 `Foo` 对应的扩展中的函数 `f`。37
38
而对于接口扩展,需要同时导入被扩展的类型、扩展的接口和泛型约束(如果有)才能使用。因此在 `package c` 中,需要同时导入 `Foo` 和 `I` 才能使用对应扩展中的函数 `g`。39
40
<!-- compile -->Code 1 · cangjie
1
// package a.b2
package a.b3
4
private interface I1 {}5
internal interface I2 {}6
protected interface I3 {}7
8
extend Int64 <: I1 & I2 & I3 {}9
10
public class Foo<T> {}11
// The extension will not be exported12
extend<T> Foo<T> where T <: I1 {13
public func f1() {}14
}15
// The extension will be exported, and only packages that import both Foo and I2 will be able to access it.16
extend<T> Foo<T> where T <: I2 {17
public func f2() {}18
}19
// The extension will be exported, and only packages that import both Foo and I3 will be able to access it.20
extend<T> Foo<T> where T <: I3 {21
public func f3() {}22
}23
// The extension will not be exported. The I1 with the lowest access level determines the export.24
extend<T> Foo<T> where T <: I1 & I2 & I3 {25
public func f4() {}26
}27
// The extension is exported. Only the package that imports Foo, I2, and I3 can access the extension.28
extend<T> Foo<T> where T <: I2 & I3 {29
public func f5() {}30
}31
32
// package a.c33
package a.c34
import a.b.*35
36
main() {37
Foo<Int64>().f1() // Cannot access.38
Foo<Int64>().f2() // Cannot access. Visible only for sub-pkg.39
Foo<Int64>().f3() // OK.40
Foo<Int64>().f4() // Cannot access.41
Foo<Int64>().f5() // Cannot access. Visible only for sub-pkg.42
}43
44
// package a.b.d45
package a.b.d46
import a.b.*47
48
main() {49
Foo<Int64>().f1() // Cannot access.50
Foo<Int64>().f2() // OK.51
Foo<Int64>().f3() // OK.52
Foo<Int64>().f4() // Cannot access.53
Foo<Int64>().f5() // OK.54
}Code 2 · cangjie
1
// package a2
package a3
4
private interface I0 {}5
6
public class Foo<T> {}7
8
// The extension is exported.9
extend<T> Foo<T> <: I0 {}Code 3 · cangjie
1
// package b2
package b3
4
import a.Foo5
6
private interface I1 {}7
internal interface I2 {}8
protected interface I3 {}9
public interface I4 {}10
11
// The extension will not be exported because I1 is not visible outside the file.12
extend<T> Foo<T> <: I1 {}13
14
// The extension is exported.15
extend<T> Foo<T> <: I2 {}16
17
// The extension is exported.18
extend<T> Foo<T> <: I3 {}19
20
// The extension is exported21
extend<T> Foo<T> <: I1 & I2 & I3 {}22
23
// The extension will not be exported. The I1 with the lowest access level determines the export.24
extend<T> Foo<T> <: I4 where T <: I1 & I2 & I3 {}25
26
// The extension is exported.27
extend<T> Foo<T> <: I4 where T <: I2 & I3 {}28
29
// The extension is exported.30
extend<T> Foo<T> <: I4 & I3 where T <: I2 {}Code 4 · cangjie
1
// package a2
package a3
4
public class Foo {}Code 5 · cangjie
1
// package b2
package b3
4
import a.Foo5
6
public interface I1 {7
func f1(): Unit8
}9
10
public interface I2 {11
func f2(): Unit12
}13
14
extend Foo <: I1 & I2 {15
public func f1(): Unit {}16
public func f2(): Unit {}17
public func f3(): Unit {} // f3 will not be exported18
}Code 6 · cangjie
1
// package c2
package c3
4
import a.Foo5
import b.I16
7
main() {8
let x: Foo = Foo()9
x.f1() // OK, because f1 is a member of I1.10
x.f2() // error, I2 is not imported11
x.f3() // error, f3 not found12
}Code 7 · cangjie
1
// package a2
package a3
public class Foo {}4
extend Foo {5
public func f() {}6
}Code 8 · cangjie
1
// package b2
package b3
import a.Foo4
5
public interface I {6
func g(): Unit7
}8
extend Foo <: I {9
public func g() {10
this.f() // OK11
}12
}Code 9 · cangjie
1
// package c2
package c3
import a.Foo4
import b.I5
6
func test() {7
let a = Foo()8
a.f() // OK9
a.g() // OK10
}v1.1.0
Section Text
1
扩展也是可以被导入和导出的,但是扩展本身不能使用可见性修饰符修饰,扩展的导出有一套特殊的规则。2
3
对于直接扩展,当扩展与被扩展的类型在同一个包中,扩展是否导出,由被扩展类型与泛型约束(如果有)的访问修饰符同时决定,当所有的泛型约束都是导出类型(修饰符与导出规则,详见[顶层声明的可见性](../package/toplevel_access.md)章节)时,该扩展将被导出。当扩展与被扩展类型不在同一个包中时,该扩展不会导出。4
5
如以下代码所示,`Foo` 是导出的,`f1` 函数所在的扩展由于不导出泛型约束,故该扩展不会被导出;`f2` 和 `f3` 函数所在的扩展的泛型约束均被导出,故该扩展被导出;`f4` 函数所在的扩展包含多个泛型约束,且泛型约束中 `I1` 未被导出,故该扩展不会被导出;`f5` 函数所在的扩展包含多个泛型约束,所有的泛型约束均是导出的,故该扩展会被导出。6
7
<!-- code_check_manual -->8
9
10
对于接口扩展则分为两种情况:11
12
1. 当接口扩展与被扩展类型在相同的 `package` 时,扩展会与被扩展类型以及泛型约束(如果有)一起被导出,不受接口类型的访问级别影响,包外不需要导入接口类型也能访问该扩展的成员。13
2. 当接口扩展与被扩展类型在不同的 `package` 时,接口扩展是否导出由接口类型以及泛型约束(如果有)里用到的类型中最小的访问级别决定。其他 `package` 必须导入被扩展类型、相应的接口以及约束用到的类型(如果有),才能访问对应接口包含的扩展成员。14
15
如下代码所示,在包 `a` 中,虽然接口访问修饰符为 `private`,但 `Foo` 的扩展仍然会被导出。16
17
<!-- compile -->18
19
20
当在其他包中为 `Foo` 类型扩展时,扩展是否导出由实现接口和泛型约束的访问修饰符决定。实现接口至少存在一个导出的接口,且所有的泛型约束均可导出时,该扩展将被导出。21
22
<!-- code_no_check -->23
24
25
特别的,接口扩展导出的成员仅限于接口中包含的成员。26
27
<!-- compile.error -access_rules3 -->28
<!-- cfg="-p a --output-type=staticlib" -->29
30
31
<!-- compile.error -access_rules3 -->32
<!-- cfg="-p b --output-type=staticlib" -->33
34
35
<!-- compile.error -access_rules3 -->36
<!-- cfg="-p c --output-type=staticlib" -->37
<!-- cfg="liba.a libb.a" -->38
39
40
与扩展的导出类似,扩展的导入也不需要显式地用 `import` 导入,扩展的导入只需要导入被扩展的类型、接口和泛型约束,就可以导入可访问的所有扩展。41
42
如下面的代码所示,在 `package b` 中,只需要导入 `Foo` 就可以使用 `Foo` 对应的扩展中的函数 `f`。43
44
而对于接口扩展,需要同时导入被扩展的类型、扩展的接口和泛型约束(如果有)才能使用。因此在 `package c` 中,需要同时导入 `Foo` 和 `I` 才能使用对应扩展中的函数 `g`。45
46
<!-- run -access_rules4 -->47
<!-- cfg="-p a --output-type=staticlib" -->48
49
50
<!-- run -access_rules4 -->51
<!-- cfg="-p b --output-type=staticlib liba.a" -->52
53
54
<!-- run -access_rules4 -->55
<!-- cfg="liba.a libb.a" -->Code 1 · cangjie
1
// package a.b2
package a.b3
4
private interface I1 {}5
internal interface I2 {}6
protected interface I3 {}7
8
extend Int64 <: I1 & I2 & I3 {}9
10
public class Foo<T> {}11
// The extension will not be exported12
extend<T> Foo<T> where T <: I1 {13
public func f1() {}14
}15
// The extension will be exported, and only packages that import both Foo and I2 will be able to access it.16
extend<T> Foo<T> where T <: I2 {17
public func f2() {}18
}19
// The extension will be exported, and only packages that import both Foo and I3 will be able to access it.20
extend<T> Foo<T> where T <: I3 {21
public func f3() {}22
}23
// The extension will not be exported. The I1 with the lowest access level determines the export.24
extend<T> Foo<T> where T <: I1 & I2 & I3 {25
public func f4() {}26
}27
// The extension is exported. Only the package that imports Foo, I2, and I3 can access the extension.28
extend<T> Foo<T> where T <: I2 & I3 {29
public func f5() {}30
}31
32
// package a.c33
package a.c34
import a.b.*35
36
main() {37
Foo<Int64>().f1() // Cannot access.38
Foo<Int64>().f2() // Cannot access. Visible only for sub-pkg.39
Foo<Int64>().f3() // OK.40
Foo<Int64>().f4() // Cannot access.41
Foo<Int64>().f5() // Cannot access. Visible only for sub-pkg.42
}43
44
// package a.b.d45
package a.b.d46
import a.b.*47
48
main() {49
Foo<Int64>().f1() // Cannot access.50
Foo<Int64>().f2() // OK.51
Foo<Int64>().f3() // OK.52
Foo<Int64>().f4() // Cannot access.53
Foo<Int64>().f5() // OK.54
}Code 2 · cangjie
1
// package a2
package a3
4
private interface I0 {}5
6
public class Foo<T> {}7
8
// The extension is exported.9
extend<T> Foo<T> <: I0 {}Code 3 · cangjie
1
// package b2
package b3
4
import a.Foo5
6
private interface I1 {}7
internal interface I2 {}8
protected interface I3 {}9
public interface I4 {}10
11
// The extension will not be exported because I1 is not visible outside the file.12
extend<T> Foo<T> <: I1 {}13
14
// The extension is exported.15
extend<T> Foo<T> <: I2 {}16
17
// The extension is exported.18
extend<T> Foo<T> <: I3 {}19
20
// The extension is exported21
extend<T> Foo<T> <: I1 & I2 & I3 {}22
23
// The extension will not be exported. The I1 with the lowest access level determines the export.24
extend<T> Foo<T> <: I4 where T <: I1 & I2 & I3 {}25
26
// The extension is exported.27
extend<T> Foo<T> <: I4 where T <: I2 & I3 {}28
29
// The extension is exported.30
extend<T> Foo<T> <: I4 & I3 where T <: I2 {}Code 4 · cangjie
1
// package a2
package a3
4
public class Foo {}Code 5 · cangjie
1
// package b2
package b3
4
import a.Foo5
6
public interface I1 {7
func f1(): Unit8
}9
10
public interface I2 {11
func f2(): Unit12
}13
14
extend Foo <: I1 & I2 {15
public func f1(): Unit {}16
public func f2(): Unit {}17
public func f3(): Unit {} // f3 will not be exported18
}Code 6 · cangjie
1
// package c2
package c3
4
import a.Foo5
import b.I16
7
main() {8
let x: Foo = Foo()9
x.f1() // OK, because f1 is a member of I1.10
x.f2() // error, I2 is not imported11
x.f3() // error, f3 not found12
}Code 7 · cangjie
1
// package a2
package a3
public class Foo {}4
extend Foo {5
public func f() {}6
}Code 8 · cangjie
1
// package b2
package b3
import a.Foo4
5
public interface I {6
func g(): Unit7
}8
extend Foo <: I {9
public func g() {10
this.f() // OK11
}12
}Code 9 · cangjie
1
// package c2
package c3
import a.Foo4
import b.I5
6
func test() {7
let a = Foo()8
a.f() // OK9
a.g() // OK10
}