We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/PoivronMax/idlize-cj-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server
# ArkTS → Cangjie 语法翻译说明
本文档基于 `pay-subset-no-gesture` 测试集的转换实践,总结 ArkTS 到 Cangjie 的语法翻译规则。
## 关于 ArkTS
ArkTS 是 OpenHarmonyOS 的应用开发语言,基于 TypeScript 扩展。本文档使用的测试集为类型定义文件(`.d.ts`),不包含具体实现代码。
### 语法基础
ArkTS 基于 TypeScript,完全兼容 TypeScript 类型系统,支持联合类型、可选类型、泛型、类与接口、枚举等特性,同时支持 `readonly` 修饰符和静态成员。
### 项目增强
本项目通过自定义 Parser 扩展了精确数值类型支持,标准 TypeScript 仅提供 `number` 类型:
- `int`/`long`/`float`/`double`(标准 TypeScript 仅支持 `number`)
- 语义化类型推断功能已移除,`number` 统一映射为 `Float64`
## 目录
1. [通用类型翻译规则](01-第一部分:通用类型翻译规则.md)
2. [组件类型翻译规则](#第二部分组件类型翻译规则)(当前文件)
3. [参数类型翻译规则](03-第三部分:参数类型翻译规则.md)
4. [特殊语法翻译](04-第四部分:特殊语法翻译.md)
5. [转换差异总结](05-第五部分:转换差异总结.md)
6. [代码生成示例](06-第六部分:代码生成示例.md)
---
## 第二部分:组件类型翻译规则
组件类型包括 `XxxInterface`(构造器接口)和 `XxxAttribute`(属性类),转换为 Component 层和 Peer 层代码。
### 2.1 组件类型 vs 参数类型识别
在 ArkTS 中,组件定义和参数定义有完全不同的结构:
1. 组件类型:包括 `XxxInterface`(构造器接口)和 `XxxAttribute`(属性类),用于定义 UI 组件
2. 参数类型:`XxxOptions` 等接口,用于定义配置对象、样式对象等数据结构
两者在命名、结构和转换方式上都有显著差异。
#### 2.1.1 识别规则
组件类型和参数类型通过以下规则识别:
组件类型的特征:
1. 命名模式:
- `XxxInterface`:组件构造器接口(interface)(如 `ButtonInterface`、`TextInterface`)
- `XxxAttribute`:组件属性类(class)(如 `ButtonAttribute`、`TextAttribute`)
2. 结构特征:
- `XxxInterface` 是 interface,包含调用签名(Call Signature),用于创建组件实例
- `XxxAttribute` 是 class,继承自 `CommonMethod<T>` 或 `ScrollableCommonMethod<T>`
- `XxxAttribute` 包含大量链式调用方法,返回类型为自身
3. 配套定义:
- 通常成对出现:`XxxInterface`(interface)+ `XxxAttribute`(class)
- 配套常量:`declare const Xxx: XxxInterface`
- 配套实例:`declare const XxxInstance: XxxAttribute`
参数类型的特征:
1. 命名模式:
- `XxxOptions`:配置接口(如 `ButtonOptions`、`GridLayoutOptions`)
- `XxxStyle`:样式接口(如 `ButtonLabelStyle`、`TextStyle`)
- 其他描述性名称(如 `Font`、`Resource`、`ConstraintSizeOptions`)
2. 结构特征:
- 只包含属性定义,没有方法
- 属性通常是可选的(使用 `?:` 语法)
- 不继承其他接口(或继承其他参数接口)
3. 用途:
- 作为组件构造器的参数
- 作为组件方法的参数
- 作为其他接口的属性类型
#### 2.1.2 命名模式分析
组件类型命名模式:
在测试集中,组件类型定义如下,看几个例子:
```typescript
// button.d.ts
declare interface ButtonInterface {
(label?: ResourceStr, options?: ButtonOptions): ButtonAttribute;
}
declare class ButtonAttribute extends CommonMethod<ButtonAttribute> {
type(value: ButtonType | undefined): ButtonAttribute;
stateEffect(value: boolean | undefined): ButtonAttribute;
fontSize(value: Length | undefined): ButtonAttribute;
// ... 大量链式方法
}
declare const Button: ButtonInterface;
declare const ButtonInstance: ButtonAttribute;
```
```typescript
// text.d.ts
declare interface TextInterface {
(content?: string | Resource, value?: TextOptions): TextAttribute;
}
declare class TextAttribute extends CommonMethod<TextAttribute> {
fontColor(value: ResourceColor | undefined): TextAttribute;
fontSize(value: Length | undefined): TextAttribute;
fontWeight(value: number | FontWeight | string | undefined): TextAttribute;
// ... 大量链式方法
}
declare const Text: TextInterface;
declare const TextInstance: TextAttribute;
```
命名规律:
- `XxxInterface`:组件构造器接口(interface)
- `XxxAttribute`:组件属性类(class)
- `Xxx`:组件常量(指向 Interface)
- `XxxInstance`:组件实例(指向 Attribute)
参数类型命名模式:
在测试集中,参数类型定义如下,看几个例子:
```typescript
// button.d.ts - 配置接口
declare interface ButtonOptions {
type?: ButtonType;
stateEffect?: boolean;
buttonStyle?: ButtonStyleMode;
controlSize?: ControlSize;
role?: ButtonRole;
}
// button.d.ts - 样式接口
declare interface ButtonLabelStyle {
overflow?: TextOverflow;
maxLines?: int;
minFontSize?: double | ResourceStr;
maxFontSize?: double | ResourceStr;
heightAdaptivePolicy?: TextHeightAdaptivePolicy;
font?: Font;
}
// grid.d.ts - 布局配置
declare interface GridLayoutOptions {
regularSize: [int, int];
irregularIndexes?: int[];
onGetIrregularSizeByIndex?: (index: int) => [int, int];
onGetRectByIndex?: (index: int) => [int, int, int, int];
}
// units.d.ts - 通用接口
declare interface Font {
size?: Length;
weight?: FontWeight | number | string;
family?: string | Resource;
style?: FontStyle;
}
```
命名规律:
- `XxxOptions`:配置接口(最常见)
- `XxxStyle`:样式接口
- 描述性名称:`Font`、`Resource`、`Padding` 等
#### 2.1.3 结构特征对比
组件类型结构,看个例子:
```typescript
// 1. 构造器接口(XxxInterface)
declare interface ButtonInterface {
// 调用签名:用于创建组件实例
(label?: ResourceStr, options?: ButtonOptions): ButtonAttribute;
// 可能有多个重载
}
// 2. 属性类(XxxAttribute)
declare class ButtonAttribute extends CommonMethod<ButtonAttribute> {
// 特征1:继承 CommonMethod<T>,使用 CRTP 模式
// 特征2:所有方法返回 ButtonAttribute(链式调用)
// 特征3:方法名通常是属性名(fontSize、fontColor 等)
// 特征4:参数通常是 Type | undefined
type(value: ButtonType | undefined): ButtonAttribute;
stateEffect(value: boolean | undefined): ButtonAttribute;
fontSize(value: Length | undefined): ButtonAttribute;
fontWeight(value: number | FontWeight | string | undefined): ButtonAttribute;
fontColor(value: ResourceColor | undefined): ButtonAttribute;
// ... 100+ 方法
}
// 3. 配套常量
declare const Button: ButtonInterface;
declare const ButtonInstance: ButtonAttribute;
```
参数 Interface 结构,看几个例子:
```typescript
// 1. 纯数据接口
declare interface ButtonOptions {
// 特征1:只有属性,没有方法
// 特征2:属性通常是可选的(?:)
// 特征3:属性类型多样(基础类型、枚举、联合类型等)
// 特征4:可能包含回调函数属性
type?: ButtonType; // 可选枚举
stateEffect?: boolean; // 可选布尔
buttonStyle?: ButtonStyleMode; // 可选枚举
controlSize?: ControlSize; // 可选枚举
role?: ButtonRole; // 可选枚举
}
// 2. 样式接口
declare interface ButtonLabelStyle {
overflow?: TextOverflow; // 可选枚举
maxLines?: int; // 可选整数
minFontSize?: double | ResourceStr; // 可选联合类型
maxFontSize?: double | ResourceStr; // 可选联合类型
heightAdaptivePolicy?: TextHeightAdaptivePolicy; // 可选枚举
font?: Font; // 可选接口类型
}
// 3. 复杂配置接口
declare interface GridLayoutOptions {
regularSize: [int, int]; // 必选元组
irregularIndexes?: int[]; // 可选数组
onGetIrregularSizeByIndex?: (index: int) => [int, int]; // 可选回调
onGetRectByIndex?: (index: int) => [int, int, int, int]; // 可选回调
}
```
对比总结表:
| 特征 | 组件 Interface | 参数 Interface |
|------|---------------|---------------|
| 命名 | `XxxInterface` + `XxxAttribute` | `XxxOptions` / `XxxStyle` / 描述性名称 |
| 成员 | 调用签名 + 方法 | 只有属性 |
| 继承 | `extends CommonMethod<T>` | 不继承或继承其他参数接口 |
| 返回类型 | 返回自身(链式调用) | N/A(没有方法) |
| 参数类型 | `Type \| undefined` | N/A(是属性不是参数) |
| 可选性 | 参数可选 | 属性可选(`?:`) |
| 用途 | 定义 UI 组件 | 定义配置对象 |
| 转换目标 | Component 层 + Peer 层 | CommonPara 层类 |
| 配套定义 | 有常量和实例 | 无配套定义 |
#### 2.1.4 识别流程
识别一个 Interface 是组件还是参数的流程,按这个步骤来:
```
1. 检查命名:
- 以 "Interface" 结尾? → 组件 Interface
- 以 "Attribute" 结尾? → 组件 Attribute
- 以 "Options" 或 "Style" 结尾? → 参数 Interface
2. 检查结构:
- 包含调用签名? → 组件 Interface
- 继承 CommonMethod<T>? → 组件 Attribute
- 只有属性定义? → 参数 Interface
3. 检查配套定义:
- 有对应的 XxxInterface 和 XxxAttribute? → 组件
- 有对应的 declare const Xxx? → 组件
- 独立定义,无配套? → 参数 Interface
4. 检查用途:
- 作为其他组件的参数? → 参数 Interface
- 返回自身类型的方法? → 组件 Attribute
```
#### 2.1.5 识别规则总结
测试集统计:
- 组件 Interface:约 10 个(`ButtonInterface`、`TextInterface`、`ImageInterface` 等)
- 组件 Attribute:约 10 个(`ButtonAttribute`、`TextAttribute`、`ImageAttribute` 等)
- 参数 Interface:约 240 个(`ButtonOptions`、`Font`、`Resource` 等)
需要注意的:
1. 命名不是绝对依据:少数参数 Interface 也可能以 "Attribute" 结尾(比如 `ComputedBarAttribute`),需要结合结构判断
2. 结构是关键:是否包含调用签名、是否继承 CommonMethod、是否只有属性,这些是最可靠的识别依据
3. 配套定义辅助判断:组件通常有完整的配套定义(Interface + Attribute + 常量 + 实例)
4. 用途反推:如果一个 Interface 被用作其他组件的参数,那它一定是参数 Interface
### 2.2 XxxInterface 构造器接口翻译
XxxInterface 是组件的构造器接口,定义了组件的创建方式。
#### 2.2.1 Interface 定义与转换
XxxInterface 定义了组件的构造器签名,用于创建组件实例。看几个例子:
```typescript
// button.d.ts - Button 组件构造器
interface ButtonInterface {
/**
* Create Button with inner text label.
*/
(label: ResourceStr, options?: ButtonOptions): ButtonAttribute;
}
declare const Button: ButtonInterface;
```
```typescript
// text.d.ts - Text 组件构造器(多参数)
interface TextInterface {
(content?: string | Resource, value?: TextOptions): TextAttribute;
}
declare const Text: TextInterface;
```
```typescript
// image.d.ts - Image 组件构造器(单参数)
interface ImageInterface {
(src: PixelMap | ResourceStr | DrawableDescriptor): ImageAttribute;
}
declare const Image: ImageInterface;
```
XxxInterface 转换为 Cangjie 的函数,使用 `@Memo` 装饰器和回调模式,转换后的代码:
```cangjie
// ArkButton.cj - Button 组件函数
public type OnButtonStyleCallback = (attributes: ArkButtonComponent) -> Unit
public type OnButtonContentCallback = () -> Unit
@Memo
public func ArkButton(
style: Option<OnButtonStyleCallback>,
content_: Option<OnButtonContentCallback>
): Unit {
let receiver = remember<ArkButtonComponent>({ =>
ArkButtonComponent()
})
NodeAttach<ArkButtonPeer>(
{ => ArkButtonPeer.create(receiver, flags: 0) },
{ =>
style?(receiver)
content_?()
receiver.applyAttributesFinish()
}
)
// 注:Peer层实现细节见序列化规则文档
}
```
```cangjie
// ArkText.cj - Text 组件函数
public type OnTextStyleCallback = (attributes: ArkTextComponent) -> Unit
public type OnTextContentCallback = () -> Unit
@Memo
public func ArkText(
style: Option<OnTextStyleCallback>,
content_: Option<OnTextContentCallback>
): Unit {
let receiver = remember<ArkTextComponent>({ =>
ArkTextComponent()
})
NodeAttach<ArkTextPeer>(
{ => ArkTextPeer.create(receiver, flags: 0) },
{ =>
style?(receiver)
content_?()
receiver.applyAttributesFinish()
}
)
// 注:Peer层实现细节见序列化规则文档
}
```
转换规则:
| ArkTS 语法 | Cangjie 转换 | 说明 |
|-----------|-------------|------|
| `interface XxxInterface` | `func ArkXxx()` | 构造器接口转为函数 |
| `(params): XxxAttribute` | `(style, content_): Unit` | 参数转为回调函数 |
| `declare const Xxx: XxxInterface` | `func ArkXxx()` | 常量声明不生成 |
| 构造器参数 | `setXxxOptions()` 方法 | 参数通过 Component 方法设置 |
关键设计:
1. **回调模式**:使用 `style` 回调设置属性,`content_` 回调设置子组件
2. **@Memo 装饰器**:用于组件缓存和优化
3. **remember 函数**:创建和记忆组件实例
4. **NodeAttach**:将组件节点附加到组件树
5. **applyAttributesFinish()**:完成属性应用
构造器参数处理:
ArkTS 构造器的参数不直接映射到 Cangjie 函数参数,而是转换为 Component 层的 `setXxxOptions()` 方法:
```typescript
// ArkTS
Button("Click", { type: ButtonType.Capsule })
```
```cangjie
// Cangjie
ArkButton(
style: Option.Some({ attributes =>
attributes.setButtonOptions(
label: Option.Some(ResourceStr.fromString("Click")),
options: Option.Some(ButtonOptions(
type_: Option.Some(ButtonType.CAPSULE),
stateEffect: Option.None,
buttonStyle: Option.None,
controlSize: Option.None,
role: Option.None
))
)
attributes.type_(Option.Some(ButtonType.CAPSULE))
}),
content_: Option.Some({ =>
// 子组件内容
})
)
```
说明:
1. 构造器接口转换为函数,不保留原始参数签名
2. 使用回调模式而非直接参数传递
3. 构造器参数通过 `setXxxOptions()` 方法设置
4. 所有组件使用统一的 `(style, content_)` 签名
#### 2.2.2 构造器参数处理
构造器参数转换为 Component 层的方法调用。构造器接口转换为 Cangjie 的函数,使用 `@Memo` 装饰器和回调模式,详细示例见 2.2.1。
### 2.3 XxxAttribute 属性类翻译
XxxAttribute 是组件的属性类(class),定义了组件的属性方法,支持链式调用。
#### 2.3.1 Attribute 类定义
测试集中的用法:
```typescript
// button.d.ts - ButtonAttribute 类
declare class ButtonAttribute extends CommonMethod<ButtonAttribute> {
/**
* Describes the button style.
*/
type(value: ButtonType | undefined): ButtonAttribute;
/**
* Set button font color.
*/
fontColor(value: ResourceColor | undefined): ButtonAttribute;
/**
* Set button label style.
*/
labelStyle(value: ButtonLabelStyle | undefined): ButtonAttribute;
}
```
```typescript
// text.d.ts - TextAttribute 类(含联合类型参数)
declare class TextAttribute extends CommonMethod<TextAttribute> {
/**
* Called when the font color is set.
*/
fontColor(value: ResourceColor | undefined): TextAttribute;
/**
* Called when the font size is set.
*/
fontSize(value: double | string | Resource | undefined): TextAttribute;
/**
* Called when the font weight is set.
*/
fontWeight(weight: number | FontWeight | string | undefined,
options?: FontSettingOptions | undefined): TextAttribute;
}
```
转换结果:
XxxAttribute 转换为 Cangjie 的 Component 类,继承自 `ArkCommonMethodComponent`:
```cangjie
// ArkButton.cj - ArkButtonComponent 类
public open class ArkButtonComponent <: ArkCommonMethodComponent {
protected func getPeer(): ArkButtonPeer {
if (let Some(peer) <- this.peer) {
return match (peer as ArkButtonPeer) {
case Some(x) => x
case None => throw Exception("Cast is not succeeded")
}
} else { throw Exception() }
}
public func setButtonOptions(label!: Option<ResourceStr> = Option.None, options!: Option<ButtonOptions> = Option.None): This {
this.getPeer().buttonOptionsAttribute(label, options)
return this
}
public func type_(value: Option<ButtonType>): This {
this.getPeer().typeAttribute(value)
return this
}
public func fontColor(value: Option<ResourceColor>): This {
this.getPeer().fontColorAttribute(value)
return this
}
public func labelStyle(value: Option<LabelStyle>): This {
this.getPeer().labelStyleAttribute(value)
return this
}
protected open func applyAttributesFinish(): Unit {
super.applyAttributesFinish()
}
}
```
```cangjie
// ArkText.cj - ArkTextComponent 类(含方法重载)
public open class ArkTextComponent <: ArkCommonMethodComponent {
protected func getPeer(): ArkTextPeer {
if (let Some(peer) <- this.peer) {
return match (peer as ArkTextPeer) {
case Some(x) => x
case None => throw Exception("Cast is not succeeded")
}
} else { throw Exception() }
}
public func setTextOptions(content!: Option<String> = Option.None, value!: Option<TextOptions> = Option.None): This {
this.getPeer().textOptionsAttribute(content, value)
return this
}
public func setTextOptions(content!: Option<Resource> = Option.None, value!: Option<TextOptions> = Option.None): This {
this.getPeer().textOptionsAttribute(content, value)
return this
}
public func fontColor(value: Option<ResourceColor>): This {
this.getPeer().fontColorAttribute(value)
return this
}
// fontSize 方法重载(联合类型参数展开)
public func fontSize(value: Option<Float64>): This {
this.getPeer().fontSizeAttribute(value)
return this
}
public func fontSize(value: Option<String>): This {
this.getPeer().fontSizeAttribute(value)
return this
}
public func fontSize(value: Option<Resource>): This {
this.getPeer().fontSizeAttribute(value)
return this
}
protected open func applyAttributesFinish(): Unit {
super.applyAttributesFinish()
}
}
```
转换规则:
| ArkTS 语法 | Cangjie 转换 | 说明 |
|-----------|-------------|------|
| `class XxxAttribute` | `class ArkXxxComponent` | 类名转换 |
| `extends CommonMethod<T>` | `<: ArkCommonMethodComponent` | 继承基类 |
| `method(value: T): XxxAttribute` | `func method(value: T): This` | 返回 This 类型 |
| 方法体 | 调用 Peer 层方法 | 委托给 Peer 层(Peer层实现细节见序列化规则文档) |
关键设计:
1. **getPeer() 方法**:类型转换,将基类 peer 转为具体 Peer 类型
2. **This 返回类型**:支持链式调用,保持类型安全
3. **方法命名**:Component 层保持原名(`fontColor`、`fontSize`)
4. **参数处理**:参数类型转换规则见第一部分(1.2 可选类型、1.7 联合类型)
5. **applyAttributesFinish()**:完成属性应用的钩子方法
### 2.4 Component 层代码生成
Component 层是用户面向的 API,负责链式调用和属性设置。
生成的文件结构:
```
cjv2/src/components/
├── ArkButton.cj # Button 组件
├── ArkText.cj # Text 组件
├── ArkImage.cj # Image 组件
├── ArkCommonMethod.cj # 通用方法基类
└── ...
```
Component 层类的结构:
```cangjie
// 1. 包声明和导入
package idlize.components
import idlize.commonPara.*
import idlize.peers.*
import std.collection.*
import Interop.*
import KoalaRuntime.*
import KoalaRuntime.memoize.*
// 2. Component 类定义
public open class ArkButtonComponent <: ArkCommonMethodComponent {
// 2.1 getPeer() 方法(类型转换)
protected func getPeer(): ArkButtonPeer { ... }
// 2.2 组件特有方法
public func type_(value: Option<ButtonType>): This { ... }
public func fontColor(value: Option<ResourceColor>): This { ... }
// 2.3 applyAttributesFinish() 钩子
protected open func applyAttributesFinish(): Unit { ... }
}
// 3. 回调类型定义
public type OnButtonStyleCallback = (attributes: ArkButtonComponent) -> Unit
public type OnButtonContentCallback = () -> Unit
// 4. 组件构造函数
@Memo
public func ArkButton(
style: Option<OnButtonStyleCallback>,
content_: Option<OnButtonContentCallback>
): Unit { ... }
```
方法生成规则:
Component 层方法的参数类型转换规则已在第一部分详细说明:
1. **可选参数**:`Type | undefined` → `Option<Type>`(详见 1.2 节)
2. **联合类型参数**:类型别名不展开,直接联合类型展开为重载(详见 1.7.3 节)
3. **回调函数参数**:转换为函数类型(详见 1.8 节)
4. **数组参数**:`Array<T>` → `ArrayList<T>`(详见 1.3 节)
方法实现模式:
```cangjie
// Component 层方法统一模式
public func methodName(value: Option<Type>): This {
this.getPeer().methodNameAttribute(value) // 委托给 Peer 层
return this
}
```
命名转换规则:
| ArkTS 方法名 | Cangjie 方法名 | 说明 |
|-------------|---------------|------|
| `type` | `type_` | 关键字冲突,添加下划线 |
| `onClick` | `onClick` | 保持不变 |
| `width` | `width` | 保持不变 |
| 其他方法 | 保持原名 | 除关键字外不变 |
### 2.5 继承关系处理
组件类的继承关系通过基类和接口实现。
ArkTS 中的继承:
```typescript
// common.d.ts - 泛型基类(CRTP 模式)
declare class CommonMethod<T> {
width(widthValue: Length | LayoutPolicy | undefined): T;
height(heightValue: Length | LayoutPolicy | undefined): T;
backgroundColor(value: ResourceColor | undefined): T;
onClick(event: ((event?: ClickEvent) => void) | undefined): T;
// ... 350+ 方法
}
// button.d.ts - 具体组件继承基类
declare class ButtonAttribute extends CommonMethod<ButtonAttribute> {
type(value: ButtonType | undefined): ButtonAttribute;
fontColor(value: ResourceColor | undefined): ButtonAttribute;
// ... 组件特有方法
}
```
Cangjie 中的转换:
```cangjie
// ArkCommonMethod.cj - 接口定义
public interface CommonMethod {
func width(widthValue: Option<Length>): This
func width(widthValue: Option<LayoutPolicy>): This
func height(heightValue: Option<Length>): This
func height(heightValue: Option<LayoutPolicy>): This
func backgroundColor(value: Option<ResourceColor>): This
func onClick(event: Option<((event: Option<ClickEvent>) -> Unit)>): This
// ... 350+ 方法签名
}
// ArkCommonMethod.cj - 基类实现
public open class ArkCommonMethodComponent <: ComponentBase & CommonMethod {
protected open func getPeer(): ArkCommonMethodPeer {
if (let Some(peer) <- this.peer) {
return match (peer as ArkCommonMethodPeer) {
case Some(x) => x
case None => throw Exception("Cast is not succeeded")
}
} else { throw Exception() }
}
public func width(widthValue: Option<Length>): This {
this.getPeer().widthAttribute(widthValue)
return this
}
public func width(widthValue: Option<LayoutPolicy>): This {
this.getPeer().widthAttribute(widthValue)
return this
}
public func height(heightValue: Option<Length>): This {
this.getPeer().heightAttribute(heightValue)
return this
}
// ... 实现所有 CommonMethod 方法
}
// ArkButton.cj - 具体组件继承基类
public open class ArkButtonComponent <: ArkCommonMethodComponent {
protected func getPeer(): ArkButtonPeer {
if (let Some(peer) <- this.peer) {
return match (peer as ArkButtonPeer) {
case Some(x) => x
case None => throw Exception("Cast is not succeeded")
}
} else { throw Exception() }
}
public func type_(value: Option<ButtonType>): This {
this.getPeer().typeAttribute(value)
return this
}
// ... 组件特有方法
}
```
继承关系转换规则:
| ArkTS 继承 | Cangjie 转换 | 说明 |
|-----------|-------------|------|
| `class CommonMethod<T>` | `interface CommonMethod` + `class ArkCommonMethodComponent` | 泛型类转为接口+基类 |
| `T` 类型参数 | `This` 类型 | 使用 This 表示当前实例类型 |
| `extends CommonMethod<ButtonAttribute>` | `<: ArkCommonMethodComponent` | 继承基类 |
| 方法返回 `T` | 方法返回 `This` | 支持链式调用 |
Peer 层的继承:
```cangjie
// ArkCommonMethodPeer.cj - Peer 基类
public open class ArkCommonMethodPeer <: PeerNode {
public func widthAttribute(widthValue: Option<Length>): Unit { ... }
public func widthAttribute(widthValue: Option<LayoutPolicy>): Unit { ... }
public func heightAttribute(heightValue: Option<Length>): Unit { ... }
// ... 所有通用方法的实现
}
// ArkButtonAttributePeer.cj - 具体组件 Peer
public open class ArkButtonPeer <: ArkCommonMethodPeer {
public func typeAttribute(value: Option<ButtonType>): Unit { ... }
public func fontColorAttribute(value: Option<ResourceColor>): Unit { ... }
// ... 组件特有方法的实现
}
```
继承层次:
```
Component 层:
ComponentBase (基础组件类)
↑
ArkCommonMethodComponent (通用方法基类)
↑
ArkButtonComponent (具体组件类)
Peer 层:
PeerNode (基础 Peer 类)
↑
ArkCommonMethodPeer (通用方法 Peer)
↑
ArkButtonPeer (具体组件 Peer)
```
关键设计:
1. **接口 + 基类模式**:`CommonMethod` 接口定义方法签名,`ArkCommonMethodComponent` 基类提供实现
2. **This 类型**:保持链式调用的类型安全,子类方法返回子类类型
3. **getPeer() 覆盖**:子类覆盖 `getPeer()` 方法,返回具体的 Peer 类型
4. **双层继承**:Component 层和 Peer 层都有对应的继承关系
### 2.6 链式调用实现
链式调用是组件 API 的核心特性,通过 `This` 类型实现。
ArkTS 中的链式调用:
```typescript
// button.d.ts
Button("Click")
.width(100) // CommonMethod 方法
.height(50) // CommonMethod 方法
.type(ButtonType.Capsule) // ButtonAttribute 方法
.fontSize(16) // ButtonAttribute 方法
.onClick(() => { ... }) // CommonMethod 方法
```
Cangjie 中的实现:
```cangjie
// 链式调用示例
ArkButton(
style: Option.Some({ attributes =>
attributes
.width(Option.Some(Length.vp(100.0))) // 返回 This (ArkButtonComponent)
.height(Option.Some(Length.vp(50.0))) // 返回 This (ArkButtonComponent)
.type_(Option.Some(ButtonType.CAPSULE)) // 返回 This (ArkButtonComponent)
.fontSize(Option.Some(Length.fp(16.0))) // 返回 This (ArkButtonComponent)
.onClick(Option.Some({ event => ... })) // 返回 This (ArkButtonComponent)
}),
content_: Option.None
)
```
This 类型的工作原理:
```cangjie
// ArkCommonMethodComponent 基类
public open class ArkCommonMethodComponent <: ComponentBase & CommonMethod {
// 基类方法返回 This
public func width(widthValue: Option<Length>): This {
this.getPeer().widthAttribute(widthValue)
return this // this 的实际类型是 ArkButtonComponent
}
public func height(heightValue: Option<Length>): This {
this.getPeer().heightAttribute(heightValue)
return this // 返回当前实例
}
}
// ArkButtonComponent 子类
public open class ArkButtonComponent <: ArkCommonMethodComponent {
// 子类方法也返回 This
public func type_(value: Option<ButtonType>): This {
this.getPeer().typeAttribute(value)
return this // this 的类型是 ArkButtonComponent
}
}
// 链式调用时的类型推导:
let button: ArkButtonComponent = ...
button
.width(...) // This = ArkButtonComponent
.height(...) // This = ArkButtonComponent
.type_(...) // This = ArkButtonComponent
.fontSize(...) // This = ArkButtonComponent
```
This 类型的优势:
1. **类型安全**:编译器知道每个方法返回的具体类型
2. **方法可见性**:可以连续调用父类方法和子类方法
3. **IDE 支持**:代码补全能正确显示所有可用方法
4. **无需泛型**:避免了泛型实例化的复杂性
对比 ArkTS 的 CRTP 模式:
| 特性 | ArkTS CRTP | Cangjie This |
|-----|-----------|-------------|
| 语法 | `class Child extends Base<Child>` | `class Child <: Base` |
| 返回类型 | `T` (泛型参数) | `This` (特殊类型) |
| 类型参数 | 需要传递子类类型 | 不需要类型参数 |
| 实现复杂度 | 较高(泛型实例化) | 较低(内置支持) |
| 类型安全 | ✅ 编译时检查 | ✅ 编译时检查 |
链式调用的限制:
1. **必须返回 This**:所有链式方法必须返回 `This` 类型
2. **不能返回具体类型**:不能写 `-> ArkButtonComponent`,必须写 `-> This`
3. **getPeer() 覆盖**:子类必须覆盖 `getPeer()` 方法,返回具体 Peer 类型
### 2.7 方法参数处理
组件方法参数的类型转换规则已在第一部分详细说明:
- **可选参数**:`Type | undefined` → `Option<Type>`(详见 1.2 节)
- **联合类型参数**:类型别名不展开,直接联合类型展开为重载(详见 1.7.3 节)
- **回调函数参数**:转换为函数类型(详见 1.8 节)
- **数组参数**:`Array<T>` → `ArrayList<T>`(详见 1.3 节)
参数和属性的处理差异:
| 位置 | 处理方式 | 原因 |
|-----|---------|------|
| **属性** | Selector 模式 | 需要存储值,必须知道实际类型 |
| **参数** | 方法重载 | 只需要传递值,类型在调用时已知 |