仓颉开发之——扩展(11)

一 概述

  • 扩展概述
  • 直接扩展
  • 接口扩展
  • 访问规则

二 扩展概述

2.1 概念

  • 扩展可以为在当前 package 可见的类型(除函数、元组、接口)添加新功能
  • 不能破坏原有类型的封装性,但希望添加额外的功能时,可以使用扩展

2.2 可以添加的功能

  • 添加成员函数
  • 添加操作符重载函数
  • 添加成员属性
  • 实现接口

2.3 不支持的功能

  1. 扩展不能增加成员变量。
  2. 扩展的函数和属性必须拥有实现。
  3. 扩展的函数和属性不能使用 open、override、 redef修饰。
  4. 扩展不能访问原类型 private 的成员

三 直接扩展

3.1 概念

直接扩展即不包含额外接口的扩展

3.2 定义

1
2
3
4
5
extend String {
public func printSize() {
println("the size is ${this.size}")
}
}

3.3 使用

1
2
3
4
main() {
let a = "123"
a.printSize() // the size is 3
}

四 接口扩展

4.1 概念

接口扩展即包含接口的扩展

4.2 定义

1
2
3
4
5
6
7
8
9
interface PrintSizeable {
func printSize(): Unit
}

extend<T> Array<T> <: PrintSizeable {
public func printSize() {
println("The size is ${this.size}")
}
}

4.3 使用

1
2
3
4
main() {
let a: PrintSizeable = Array<Int64>()
a.printSize() // 0
}

五 访问规则

5.1 扩展的修饰符

1-扩展成员可使用的修饰符有:static、public、protected(仅限于被扩展类型是 class 类型)、private、mut。

  • 使用 private 修饰的成员只能在本扩展内使用,外部不可见。
  • 使用 protected 修饰的成员除了能在本包内被访问,对包外的当前 class 子类也可以访问。
  • 没有使用 private,protected 或 public 修饰的成员只能在本包内使用。
  • 使用 static 修饰的成员,只能通过类型名访问,不能通过实例对象访问。
  • 对 struct 类型的扩展可以定义 mut 函数。

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package p1

public open class A {}

extend A {
public func f1() {}
protected func f2() {}
private func f3() {}
static func f4() {}
}

main() {
A.f4()
var a = A()
a.f1()
a.f2()
}

2-扩展内的成员定义不支持使用 open、override、redef 修饰

1
2
3
4
5
6
7
8
9
10
class Foo {
public open func f() {}
static func h() {}
}

extend Foo {
public override func f() {} // Error
public open func g() {} // Error
redef static func h() {} // Error
}

5.2 扩展的孤儿规则

仓颉不允许定义孤儿扩展,指的是既不与接口(包含接口继承链上的所有接口)定义在同一个包中,也不与被扩展类型定义在同一个包中的接口扩展

1
2
3
4
5
6
7
8
9
10
11
// package a
public class Foo {}

// package b
public interface Bar {}

// package c
import a.Foo
import b.Bar

extend Foo <: Bar {} // Error

5.3 扩展的访问和遮盖

1
2
3
4
5
6
7
8
9
10
class A {
var v = 0
}

extend A {
func f() {
print(this.v) // ok
print(v) // ok
}
}

5.4 扩展的导入导出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package a

public class Foo {}

extend Foo {
public func f() {}
}

///////

package b
import a.*

extend Foo {
public func g() {}
}

///////

package c
import a.*
import b.*

main() {
let a = Foo()
a.f() // OK
a.g() // Error
}

六 思维导图

七 参考

  • 仓颉官方文档—扩展
  • 仓颉编程语言入门教程