issue地址
描述
为什么StringBuilder可以append不同类型的变量。
仓颉中的类型泛型是不型变的,为什么如下的代码可以编译通过
代码
func issue1548() {
let sb = StringBuilder()
sb.append(r'7', 3, false, 1.2, 'str')
print(sb)
}
分析
我们首先找到StringBuilder的append方法,它有很多重载的append方法
符合代码中使用的形式如下
为什么是这个形式的append函数,因为仓颉中关于变长参数有如下的说法
我们分析一下为什么能够通过编译
首先代码中传给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)
}