## **KQCode** 除了工具类,有些时候封装类依旧还是有些用处的。此模组中提供了一个`KQCode`类型,代表对一个CQ码的包装。 <br> `KQCode`在模组`1.8.0`版本的时候变更为了接口类型,并提供若干不同形式的实现类。 - ##### **参数可变性** <hr> KQCode实现了 **`Map<String, String>`** 接口与 **`CharSequence`** 接口,但是从 **`1.5.0-1.15`** 版本开始,KQCode被更改为了**不可变类**,因此一个普通的KQCode实例是不可以执行put、remove等修改操作的。 你可以通过KQCode实例的`mutable()`方法将`KQCode`转化为参数可变的`MutableKQCode`,或者通过`immutable()`方法转化为参数不可变的`KQKode`实例。 ```java // 作为map使用 Map<String, String> kqMap = new KQCode("at", "qq=123456789"); System.out.println(kqMap); // 作为CharSequence使用 CharSequence kqCharSequence = new KQCode("at", "qq=123456789"); System.out.println(kqCharSequence); ``` <br><br> - ##### **构建KQCode** <hr> ~~`KQCode`是一个封装类,因此它不是单例的。如果要使用它,可通过其构造方法或静态方法获取。~~ `KQCode`是一个接口类型,你可以: - 通过`KQCodeUtils`的与`kq`相关的方法(例如`toKq(...)`)构建一个`KQCode`实例 - 使用模组内提供的实现类(例如`FastKQCode`、`MapKQCode`、`EmptyKQCode`)的静态方法构建一个`KQCode`实例 - 自行实现`KQCode`接口 由于使用`KQCodeUtils`构建实例的实例代码在`CQ码操作工具类`章节里已经出现过了,此处便只展示使用第二种方法的示例: ```java // 通过KQCode静态方法构建: // 通过一个完整的CQ码字符串构建 KQCode at = KQCode.of("[CQ:at,qq=123456]"); // 通过一个没有参数的纯类型构建 KQCode share = KQCode.ofType("share"); // 通过实现类构建: // 通过一个完整的CQ码字符串构建, 使用的是FastKQCode FastKQCode fastKQCodeAt = FastKQCode.byCode("[CQ:at,qq=123456789]"); // 通过一个完整的CQ码字符串构建,使用的是MapKQCode MapKQCode mapKQCodeAt = MapKQCode.byCode("[CQ:at,qq=123456789]"); // 通过类型和参数字符串构建,使用的是MapKQCode MapKQCode mapByParamAt = MapKQCode.byParamString("at", "qq=123", "display=@bot"); // 通过类型和Map参数列表构建,使用的是MapKQCode Map<String, String> params = new HashMap<>(); params.put("qq", "123456789"); MapKQCode mapByMapAt = MapKQCode.byMap("at", params); // 通过一个完整的CQ码字符串构建(可变类型),使用的是MutableMapKQCode MutableMapKQCode mutableMapKQCodeAt = MapKQCode.mutableByCode("[CQ:at,qq=123456789]"); // 通过类型和参数字符串构建(可变类型),使用的是MutableMapKQCode MapKQCode mutableMapByParamAt = MapKQCode.mutableByParamString("at", "qq=123", "display=@bot"); // 通过类型和Map参数列表构建(可变类型),使用的是MutableMapKQCode Map<String, String> params2 = new HashMap<>(); params.put("qq", "123456789"); MapKQCode mutableMapByMapAt = MapKQCode.mutableByMap("at", params2); // 构建一个没有参数的KQCode, 使用的是EmptyKQCode EmptyKQCode dice = new EmptyKQCode("dice"); ``` >[info] 除了通过静态方法与`KQCodeUtils`的方法,你也可以使用载体为`KQCode`类型的模板,例如`KQCodeUtils`的`getKqCodeTemplate()` >[info] 关于`FastKQCode`、`MapKQCode`、`MutableMapKQCode`、`EmptyKQCode`之间的区别,可以参考他们各自的doc注释。 <br><br> - ##### **KQCode与CQCode** <hr> 除了普通的通过字符串构建,KQCode在依赖了simple-robot核心的情况下可以实现与`CQCode`相互转化。 **但是一切与`CQCode`的相互操作均不被推荐,并可能会在未来被删除。** ```java // 构建一个at的CQCode final CQCode cqCodeAt = CQCode.of(CQCodeTypes.at, new String[]{"qq=123456789"}); System.out.println(cqCodeAt); // 转化为KQCode final KQCode kqCodeAt = KQCode.of(cqCodeAt); System.out.println(kqCodeAt); // 转回CQCode final CQCode newCqCodeAt = kqCodeAt.toCQCode(); System.out.println(newCqCodeAt); ``` <br> <br><br> <br><br> ## **KQCode for DSL** 当你使用kt文件使用KQCode的时候,你可以通过偏向于DSL风格的代码来构建一个KQCode对象。 你用两种方法,第一种是提前指定CQ码的类型,而第二种则在代码块种执行。需要注意的是,如果在使用第二种方法的时候没有去指定CQ码的类型,则其类型为空字符串。 ```kotlin // import com.simplerobot.modules.utils.kqCode // import com.simplerobot.modules.utils.params // DSL to KQCode 1 val kq1 = kqCode("at") { param = "key1" to "1" param = "key2" to "2" param = "key3" to "3" param = "key4" to "4" } // DSL to KQCode 2 val kq2 = kqCode { type = "at" params { param = "qq" to "1149" param = "file" to "cq.jpg&&" } } println(kq1) println(kq2) ``` >[success] 输出结果为: > [CQ:at,key1=1,key2=2,key3=3,key4=4] > [CQ:at,qq=1149,file=cq.jpg&amp;amp;&amp;amp;] 简单来讲,即: ```kotlin kqCode("CQ码类型") { param = "参数1键" to "参数1值" param = "参数2键" to "参数2值" ... } ``` 或 ```kotlin kqCode { type ="CQ码类型" params { param = "参数1键" to "参数1值" param = "参数2键" to "参数2值" ... } } ``` <br><br>