仓颉-issue解答1548-StringBuilder的append方法的泛型应用

290 阅读1分钟

issue地址

gitcode.com/Cangjie/Use…

描述

为什么StringBuilder可以append不同类型的变量。

仓颉中的类型泛型是不型变的,为什么如下的代码可以编译通过

代码

func issue1548() {
    let sb = StringBuilder()
    sb.append(r'7', 3, false, 1.2, 'str')
    print(sb)
}

分析

我们首先找到StringBuilder的append方法,它有很多重载的append方法

image.png

符合代码中使用的形式如下

image.png

为什么是这个形式的append函数,因为仓颉中关于变长参数有如下的说法

image.png

我们分析一下为什么能够通过编译

首先代码中传给append函数的实参是字面量 r'7', 3, false, 1.2, 'str',而仓颉中基本类型都实现了ToString接口,编译器结合append函数的形参要求,将参数推断为Array<ToString>

其他代码探索

func issue1548() {
    let sb = StringBuilder()
    // String
    let a = 'str'
    // Array也是泛型,如果不标注类型,会报下面的错误
    // inconsistent element type for array literal, Traces: The types 'Bool', 'Float64', 'Int64', 'Rune' and 'Struct-String' do not have the smallest common supertype
    // let args0 = [r'7', 3, false, 1.2, a]
    // 这里args类型标注为Array<ToString>,虽然a是String类型,但由于String实现了ToString接口,它是ToString的子类型。
    // 而泛型型变是指整体赋值的时候的约束。所以这里a依然可以放入args
    var args:Array<ToString> = [r'7', 3, false, 1.2, a]
    var args2 = ['a','b','c']
    // 不型变指的是整体赋值的时候不型变
    // mismatched types expected 'Struct-Array<Interface-ToString>', found 'Struct-Array<Struct-String>'
    // args = args2
    sb.append([r'7', 3, false, 1.2, a])
    sb.append(args)
    sb.append(args2)
    print(sb)
}