1# \@BuilderParam装饰器:引用\@Builder函数 2<!--Kit: ArkUI--> 3<!--Subsystem: ArkUI--> 4<!--Owner: @zhangboren--> 5<!--Designer: @zhangboren--> 6<!--Tester: @TerryTsao--> 7<!--Adviser: @zhang_yixin13--> 8 9当开发者创建自定义组件并需要为其添加特定功能(例如:点击跳转操作)时,如果直接在组件内嵌入事件方法,会导致所有该自定义组件的实例都增加此功能。为了解决组件功能定制化的问题,ArkUI引入了@BuilderParam装饰器。@BuilderParam用于装饰指向@Builder方法的变量,开发者可以在初始化自定义组件时,使用不同的方式(例如:参数修改、尾随闭包、借用箭头函数等)对@BuilderParam装饰的自定义构建函数进行传参赋值。在自定义组件内部,通过调用@BuilderParam为组件增加特定功能。该装饰器用于声明任意UI描述的元素,类似于slot占位符。 10 11在阅读本文档前,建议提前阅读:[\@Builder](./arkts-builder.md)。 12 13> **说明:** 14> 15> 从API version 9开始,该装饰器支持在ArkTS卡片中使用。 16> 17> 从API version 11开始,该装饰器支持在原子化服务中使用。 18 19 20## 装饰器使用说明 21 22 23### 初始化\@BuilderParam装饰的方法 24 25\@BuilderParam装饰的方法只能被自定义构建函数(\@Builder装饰的方法)初始化。 26 27- 使用所属自定义组件的自定义构建函数或者全局的自定义构建函数,在本地初始化\@BuilderParam。 28 29 ```ts 30 @Builder 31 function overBuilder() { 32 } 33 34 @Component 35 struct Child { 36 @Builder 37 doNothingBuilder() { 38 } 39 40 // 使用自定义组件的自定义构建函数初始化@BuilderParam 41 @BuilderParam customBuilderParam: () => void = this.doNothingBuilder; 42 // 使用全局自定义构建函数初始化@BuilderParam 43 @BuilderParam customOverBuilderParam: () => void = overBuilder; 44 45 build() { 46 } 47 } 48 ``` 49 50- 用父组件自定义构建函数初始化子组件\@BuilderParam装饰的方法。 51 52 ```ts 53 @Component 54 struct Child { 55 @Builder 56 customBuilder() { 57 } 58 59 @BuilderParam customBuilderParam: () => void = this.customBuilder; 60 61 build() { 62 Column() { 63 this.customBuilderParam() 64 } 65 } 66 } 67 68 @Entry 69 @Component 70 struct Parent { 71 @Builder 72 componentBuilder() { 73 Text(`Parent builder `) 74 } 75 76 build() { 77 Column() { 78 Child({ customBuilderParam: this.componentBuilder }) 79 } 80 } 81 } 82 ``` 83 **图1** 示例效果图 84 85  86 87 88- 需要注意this的指向。 89 90 this指向示例如下: 91 92 ```ts 93 @Component 94 struct Child { 95 label: string = 'Child'; 96 97 @Builder 98 customBuilder() { 99 } 100 101 @Builder 102 customChangeThisBuilder() { 103 } 104 105 @BuilderParam customBuilderParam: () => void = this.customBuilder; 106 @BuilderParam customChangeThisBuilderParam: () => void = this.customChangeThisBuilder; 107 108 build() { 109 Column() { 110 this.customBuilderParam() 111 this.customChangeThisBuilderParam() 112 } 113 } 114 } 115 116 @Entry 117 @Component 118 struct Parent { 119 label: string = 'Parent'; 120 121 @Builder 122 componentBuilder() { 123 Text(`${this.label}`) 124 } 125 126 build() { 127 Column() { 128 // 调用this.componentBuilder()时,this指向当前@Entry所装饰的Parent组件,即label变量的值为'Parent'。 129 this.componentBuilder() 130 Child({ 131 // 把this.componentBuilder传给子组件Child的@BuilderParam customBuilderParam,this指向的是子组件Child,即label变量的值为'Child'。 132 customBuilderParam: this.componentBuilder, 133 // 把():void=>{this.componentBuilder()}传给子组件Child的@BuilderParam customChangeThisBuilderParam, 134 // 因为箭头函数的this指向的是宿主对象,所以label变量的值为'Parent'。 135 customChangeThisBuilderParam: (): void => { 136 this.componentBuilder() 137 } 138 }) 139 } 140 } 141 } 142 ``` 143 **图2** 示例效果图 144 145  146 147 148## 限制条件 149 150- 使用`@BuilderParam`装饰的变量只能通过`@Builder`函数进行初始化。具体参见[@BuilderParam装饰器初始化的值必须为@Builder](#builderparam装饰器初始化的值必须为builder)。 151 152- 当@Require装饰器和@BuilderParam装饰器一起使用时,@BuilderParam装饰器必须进行初始化。具体请参见[@Require装饰器和@BuilderParam装饰器联合使用](#require装饰器和builderparam装饰器联合使用)。 153 154- 在自定义组件尾随闭包的场景下,子组件有且仅有一个\@BuilderParam用来接收此尾随闭包,且此\@BuilderParam装饰的方法不能有参数。详情见[尾随闭包初始化组件](#尾随闭包初始化组件)。 155 156## 使用场景 157 158### 参数初始化组件 159 160`@BuilderParam`装饰的方法为有参数或无参数两种形式,需与指向的`@Builder`方法类型匹配。 161 162```ts 163class Tmp { 164 label: string = ''; 165} 166 167@Builder 168function overBuilder($$: Tmp) { 169 Text($$.label) 170 .width(400) 171 .height(50) 172 .backgroundColor(Color.Green) 173} 174 175@Component 176struct Child { 177 label: string = 'Child'; 178 179 @Builder 180 customBuilder() { 181 } 182 183 // 无参数类型,指向的customBuilder也是无参数类型 184 @BuilderParam customBuilderParam: () => void = this.customBuilder; 185 // 有参数类型,指向的overBuilder也是有参数类型的方法 186 @BuilderParam customOverBuilderParam: ($$: Tmp) => void = overBuilder; 187 188 build() { 189 Column() { 190 this.customBuilderParam() 191 this.customOverBuilderParam({ label: 'global Builder label' }) 192 } 193 } 194} 195 196@Entry 197@Component 198struct Parent { 199 label: string = 'Parent'; 200 201 @Builder 202 componentBuilder() { 203 Text(`${this.label}`) 204 } 205 206 build() { 207 Column() { 208 this.componentBuilder() 209 Child({ customBuilderParam: this.componentBuilder, customOverBuilderParam: overBuilder }) 210 } 211 } 212} 213``` 214**图3** 示例效果图 215 216 217 218 219### 尾随闭包初始化组件 220 221在自定义组件中,使用\@BuilderParam装饰的属性可通过尾随闭包进行初始化。初始化时,组件后需紧跟一个大括号“{}”形成尾随闭包场景。 222 223> **说明:** 224> 225> - 此场景下自定义组件内仅有一个使用\@BuilderParam装饰的属性。 226> 227> - 此场景下自定义组件不支持通用属性。 228 229开发者可以将尾随闭包内的内容看作\@Builder装饰的函数传给\@BuilderParam。 230 231示例1: 232 233```ts 234@Component 235struct CustomContainer { 236 @Prop header: string = ''; 237 238 @Builder 239 closerBuilder() { 240 } 241 242 // 使用父组件的尾随闭包{}(@Builder装饰的方法)初始化子组件@BuilderParam 243 @BuilderParam closer: () => void = this.closerBuilder; 244 245 build() { 246 Column() { 247 Text(this.header) 248 .fontSize(30) 249 this.closer() 250 } 251 } 252} 253 254@Builder 255function specificParam(label1: string, label2: string) { 256 Column() { 257 Text(label1) 258 .fontSize(30) 259 Text(label2) 260 .fontSize(30) 261 } 262} 263 264@Entry 265@Component 266struct CustomContainerUser { 267 @State text: string = 'header'; 268 269 build() { 270 Column() { 271 // 创建CustomContainer,在创建CustomContainer时,通过其后紧跟一个大括号“{}”形成尾随闭包 272 // 作为传递给子组件CustomContainer @BuilderParam closer: () => void的参数 273 CustomContainer({ header: this.text }) { 274 Column() { 275 specificParam('testA', 'testB') 276 }.backgroundColor(Color.Yellow) 277 .onClick(() => { 278 this.text = 'changeHeader'; 279 }) 280 } 281 } 282 } 283} 284``` 285**图4** 示例效果图 286 287 288 289使用全局`@Builder`和局部`@Builder`通过尾随闭包的形式对`@ComponentV2`装饰的自定义组件中的`@BuilderParam`进行初始化。 290 291示例2: 292 293```ts 294@ComponentV2 295struct ChildPage { 296 @Require @Param message: string = ''; 297 298 @Builder 299 customBuilder() { 300 } 301 302 @BuilderParam customBuilderParam: () => void = this.customBuilder; 303 304 build() { 305 Column() { 306 Text(this.message) 307 .fontSize(30) 308 .fontWeight(FontWeight.Bold) 309 this.customBuilderParam() 310 } 311 } 312} 313 314const builder_value: string = 'Hello World'; 315 316@Builder 317function overBuilder() { 318 Row() { 319 Text(`全局 Builder: ${builder_value}`) 320 .fontSize(20) 321 .fontWeight(FontWeight.Bold) 322 } 323} 324 325@Entry 326@ComponentV2 327struct ParentPage { 328 @Local label: string = 'Parent Page'; 329 330 @Builder 331 componentBuilder() { 332 Row() { 333 Text(`局部 Builder :${this.label}`) 334 .fontSize(20) 335 .fontWeight(FontWeight.Bold) 336 } 337 } 338 339 build() { 340 Column() { 341 ChildPage({ message: this.label }) { 342 Column() { // 使用局部@Builder,通过组件后紧跟一个大括号“{}”形成尾随闭包去初始化自定义组件@BuilderParam 343 this.componentBuilder(); 344 } 345 } 346 347 Line() 348 .width('100%') 349 .height(10) 350 .backgroundColor('#000000').margin(10) 351 ChildPage({ message: this.label }) { // 使用全局@Builder,通过组件后紧跟一个大括号“{}”形成尾随闭包去初始化自定义组件@BuilderParam 352 Column() { 353 overBuilder(); 354 } 355 } 356 } 357 } 358} 359``` 360 361### 使用\@BuilderParam隔离多组件对\@Builder跳转逻辑的调用 362 363当@Builder封装的系统组件包含跳转逻辑时,所有调用该@Builder的自定义组件将具备该跳转功能。对于需要禁用跳转的特定组件,可使用@BuilderParam来隔离跳转逻辑。 364 365> **说明:** 366> 367> 当前示例代码中使用了Navigation组件导航,具体实现逻辑可以查询[Navigation](../arkts-navigation-navigation.md)指南。 368 369```ts 370import { HelloWorldPageBuilder } from './helloworld'; 371 372class navigationParams { 373 pathStack: NavPathStack = new NavPathStack(); 374 boo: boolean = true; 375} 376 377@Builder 378function navigationAction(params: navigationParams) { 379 Column() { 380 Navigation(params.pathStack) { 381 Button('router to page', { stateEffect: true, type: ButtonType.Capsule }) 382 .width('80%') 383 .height(40) 384 .margin(20) 385 .onClick(() => { 386 // 通过修改@BuilderParam参数决定是否跳转。 387 if (params.boo) { 388 params.pathStack.pushPath({ name: 'HelloWorldPage' }); 389 } else { 390 console.info('@BuilderParam setting does not jump'); 391 } 392 }) 393 } 394 .navDestination(HelloWorldPageBuilder) 395 .hideTitleBar(true) 396 .height('100%') 397 .width('100%') 398 } 399 .height('25%') 400 .width('100%') 401} 402 403@Entry 404@Component 405struct ParentPage { 406 @State info: navigationParams = new navigationParams(); 407 408 build() { 409 Column() { 410 Text('ParentPage') 411 navigationAction({ pathStack: this.info.pathStack, boo: true }) 412 ChildPageOne() 413 ChildPage_BuilderParam({ eventBuilder: navigationAction }) 414 } 415 .height('100%') 416 .width('100%') 417 } 418} 419 420@Component 421struct ChildPageOne { 422 @State info: navigationParams = new navigationParams(); 423 424 build() { 425 Column() { 426 Text('ChildPage') 427 navigationAction({ pathStack: this.info.pathStack, boo: true }) 428 } 429 } 430} 431 432@Component 433struct ChildPage_BuilderParam { 434 @State info: navigationParams = new navigationParams(); 435 @BuilderParam eventBuilder: (param: navigationParams) => void = navigationAction; 436 437 build() { 438 Column() { 439 Text('ChildPage_BuilderParam') 440 // 对传递过来的全局@Builder进行参数修改,可以实现禁用点击跳转的功能。 441 this.eventBuilder({ pathStack: this.info.pathStack, boo: false }) 442 } 443 } 444} 445``` 446 447```ts 448// helloworld.ets 449@Builder 450export function HelloWorldPageBuilder() { 451 HelloWorldPage() 452} 453 454@Component 455struct HelloWorldPage { 456 @State message: string = 'Hello World'; 457 @State pathStack: NavPathStack = new NavPathStack(); 458 459 build() { 460 NavDestination() { 461 Column() { 462 Text(this.message) 463 .fontSize(20) 464 .fontWeight(FontWeight.Bold) 465 } 466 } 467 .height('100%') 468 .width('100%') 469 } 470} 471``` 472 473```ts 474// router_map.json 475{ 476 "routerMap": [ 477 { 478 "name": "HelloWorldPage", 479 "buildFunction": "HelloWorldPageBuilder", 480 "pageSourceFile": "src/main/ets/pages/helloworld.ets" 481 } 482 ] 483} 484``` 485 486```ts 487// module.json5 488{ 489 "module": { 490 "routerMap": "$profile:router_map", 491 ...... 492 } 493} 494``` 495 496**图5** 示例效果图 497 498 499 500### 使用全局和局部\@Builder初始化\@BuilderParam 501 502在自定义组件中,使用\@BuilderParam装饰的变量接收父组件通过\@Builder传递的内容进行初始化,由于父组件的\@Builder可以使用箭头函数改变当前的this指向,因此使用\@BuilderParam装饰的变量会展示不同的内容。 503 504```ts 505@Component 506struct ChildPage { 507 label: string = 'Child Page'; 508 509 @Builder 510 customBuilder() { 511 } 512 513 @BuilderParam customBuilderParam: () => void = this.customBuilder; 514 @BuilderParam customChangeThisBuilderParam: () => void = this.customBuilder; 515 516 build() { 517 Column() { 518 this.customBuilderParam() 519 this.customChangeThisBuilderParam() 520 } 521 } 522} 523 524const builder_value: string = 'Hello World'; 525 526@Builder 527function overBuilder() { 528 Row() { 529 Text(`全局 Builder: ${builder_value}`) 530 .fontSize(20) 531 .fontWeight(FontWeight.Bold) 532 } 533} 534 535@Entry 536@Component 537struct ParentPage { 538 label: string = 'Parent Page'; 539 540 @Builder 541 componentBuilder() { 542 Row() { 543 Text(`局部 Builder :${this.label}`) 544 .fontSize(20) 545 .fontWeight(FontWeight.Bold) 546 } 547 } 548 549 build() { 550 Column() { 551 // 调用this.componentBuilder()时,this指向当前@Entry所装饰的ParentPage组件,所以label变量的值为'Parent Page'。 552 this.componentBuilder() 553 ChildPage({ 554 // 把this.componentBuilder传给子组件ChildPage的@BuilderParam customBuilderParam,this指向的是子组件ChildPage,所以label变量的值为'Child Page'。 555 customBuilderParam: this.componentBuilder, 556 // 把():void=>{this.componentBuilder()}传给子组件ChildPage的@BuilderParam customChangeThisBuilderParam, 557 // 因为箭头函数的this指向的是宿主对象,所以label变量的值为'Parent Page'。 558 customChangeThisBuilderParam: (): void => { 559 this.componentBuilder() 560 } 561 }) 562 Line() 563 .width('100%') 564 .height(10) 565 .backgroundColor('#000000').margin(10) 566 // 调用全局overBuilder()时,this指向当前整个活动页,所以展示的内容为'Hello World'。 567 overBuilder() 568 ChildPage({ 569 // 把全局overBuilder传给子组件ChildPage的@BuilderParam customBuilderParam,this指向当前整个活动页,所以展示的内容为'Hello World'。 570 customBuilderParam: overBuilder, 571 // 把全局overBuilder传给子组件ChildPage的@BuilderParam customChangeThisBuilderParam,this指向当前整个活动页,所以展示的内容为'Hello World'。 572 customChangeThisBuilderParam: overBuilder 573 }) 574 } 575 } 576} 577``` 578**图6** 示例效果图 579 580 581 582### 在@ComponentV2装饰的自定义组件中使用@BuilderParam 583 584使用全局@Builder和局部@Builder初始化@ComponentV2装饰的自定义组件中的@BuilderParam属性。 585 586```ts 587@ComponentV2 588struct ChildPage { 589 @Param label: string = 'Child Page'; 590 591 @Builder 592 customBuilder() { 593 } 594 595 @BuilderParam customBuilderParam: () => void = this.customBuilder; 596 @BuilderParam customChangeThisBuilderParam: () => void = this.customBuilder; 597 598 build() { 599 Column() { 600 this.customBuilderParam() 601 this.customChangeThisBuilderParam() 602 } 603 } 604} 605 606const builder_value: string = 'Hello World'; 607 608@Builder 609function overBuilder() { 610 Row() { 611 Text(`全局 Builder: ${builder_value}`) 612 .fontSize(20) 613 .fontWeight(FontWeight.Bold) 614 } 615} 616 617@Entry 618@ComponentV2 619struct ParentPage { 620 @Local label: string = 'Parent Page'; 621 622 @Builder 623 componentBuilder() { 624 Row() { 625 Text(`局部 Builder :${this.label}`) 626 .fontSize(20) 627 .fontWeight(FontWeight.Bold) 628 } 629 } 630 631 build() { 632 Column() { 633 // 调用this.componentBuilder()时,this指向当前@Entry所装饰的ParentPage组件,所以label变量的值为'Parent Page'。 634 this.componentBuilder() 635 ChildPage({ 636 // 把this.componentBuilder传给子组件ChildPage的@BuilderParam customBuilderParam,this指向的是子组件ChildPage,所以label变量的值为'Child Page'。 637 customBuilderParam: this.componentBuilder, 638 // 把():void=>{this.componentBuilder()}传给子组件ChildPage的@BuilderParam customChangeThisBuilderPara 639 // 因为箭头函数的this指向的是宿主对象,所以label变量的值为'Parent Page'。 640 customChangeThisBuilderParam: (): void => { 641 this.componentBuilder() 642 } 643 }) 644 Line() 645 .width('100%') 646 .height(5) 647 .backgroundColor('#000000').margin(10) 648 // 调用全局overBuilder()时,this指向当前整个活动页,所以展示的内容为'Hello World'。 649 overBuilder() 650 ChildPage({ 651 // 把全局overBuilder传给子组件ChildPage的@BuilderParam customBuilderParam,this指向当前整个活动页,所以展示的内容为'Hello World'。 652 customBuilderParam: overBuilder, 653 // 把全局overBuilder传给子组件ChildPage的@BuilderParam customChangeThisBuilderParam,this指向当前整个活动页,所以展示的内容为'Hello World'。 654 customChangeThisBuilderParam: overBuilder 655 }) 656 } 657 } 658} 659``` 660**图7** 示例效果图 661 662 663 664 665## 常见问题 666 667### 改变内容UI不刷新 668 669调用自定义组件ChildPage时,通过`this.componentBuilder`形式传递`@Builder`参数。由于`this`指向自定义组件内部,因此在父组件中改变`label`的值时,自定义组件ChildPage无法感知到这一变化。 670 671【反例】 672 673```ts 674@Component 675struct ChildPage { 676 @State label: string = 'Child Page'; 677 678 @Builder 679 customBuilder() { 680 } 681 682 @BuilderParam customChangeThisBuilderParam: () => void = this.customBuilder; 683 684 build() { 685 Column() { 686 this.customChangeThisBuilderParam() 687 } 688 } 689} 690 691@Entry 692@Component 693struct ParentPage { 694 @State label: string = 'Parent Page'; 695 696 @Builder 697 componentBuilder() { 698 Row() { 699 Text(`Builder :${this.label}`) 700 .fontSize(20) 701 .fontWeight(FontWeight.Bold) 702 } 703 } 704 705 build() { 706 Column() { 707 ChildPage({ 708 // 当前写法this指向ChildPage组件内 709 customChangeThisBuilderParam: this.componentBuilder 710 }) 711 Button('点击改变label内容') 712 .onClick(() => { 713 this.label = 'Hello World'; 714 }) 715 } 716 } 717} 718``` 719 720使用箭头函数将`@Builder`传递到自定义组件`ChildPage`中,这样`this`指向会停留在父组件`ParentPage`里。因此,在父组件中改变`label`的值时,`ChildPage`会感知到并重新渲染UI。 721 722【正例】 723 724```ts 725@Component 726struct ChildPage { 727 @State label: string = 'Child Page'; 728 729 @Builder 730 customBuilder() { 731 } 732 733 @BuilderParam customChangeThisBuilderParam: () => void = this.customBuilder; 734 735 build() { 736 Column() { 737 this.customChangeThisBuilderParam() 738 } 739 } 740} 741 742@Entry 743@Component 744struct ParentPage { 745 @State label: string = 'Parent Page'; 746 747 @Builder 748 componentBuilder() { 749 Row() { 750 Text(`Builder :${this.label}`) 751 .fontSize(20) 752 .fontWeight(FontWeight.Bold) 753 } 754 } 755 756 build() { 757 Column() { 758 ChildPage({ 759 customChangeThisBuilderParam: () => { 760 this.componentBuilder() 761 } 762 }) 763 Button('点击改变label内容') 764 .onClick(() => { 765 this.label = 'Hello World'; 766 }) 767 } 768 } 769} 770``` 771 772### @Require装饰器和@BuilderParam装饰器联合使用 773 774由于@Require装饰器所装饰的变量需进行初始化,若变量未初始化,在编译时会输出报错信息。 775 776【反例】 777 778```ts 779@Builder 780function globalBuilder() { 781 Text('Hello World') 782} 783 784@Entry 785@Component 786struct CustomBuilderDemo { 787 build() { 788 Column() { 789 // 由于未对子组件ChildBuilder进行赋值,此处无论是编译还是编辑,均会报错。 790 ChildPage() 791 } 792 } 793} 794 795@Component 796struct ChildPage { 797 @Require @BuilderParam ChildBuilder: () => void = globalBuilder; 798 799 build() { 800 Column() { 801 this.ChildBuilder() 802 } 803 } 804} 805``` 806 807对@Require装饰的变量进行外部传入初始化。 808 809【正例】 810 811```ts 812@Builder 813function globalBuilder() { 814 Text('Hello World') 815} 816 817@Entry 818@Component 819struct CustomBuilderDemo { 820 build() { 821 Column() { 822 ChildPage({ ChildBuilder: globalBuilder }) 823 } 824 } 825} 826 827@Component 828struct ChildPage { 829 @Require @BuilderParam ChildBuilder: () => void = globalBuilder; 830 831 build() { 832 Column() { 833 this.ChildBuilder() 834 } 835 } 836} 837``` 838 839### @BuilderParam装饰器初始化的值必须为@Builder 840 841使用`@State`装饰器装饰的变量,给子组件的`@BuilderParam`和`ChildBuilder`变量初始化时,编译时会输出报错信息。 842 843【反例】 844 845```ts 846@Builder 847function globalBuilder() { 848 Text('Hello World') 849} 850 851@Entry 852@Component 853struct CustomBuilderDemo { 854 @State message: string = ''; 855 856 build() { 857 Column() { 858 // 子组件ChildBuilder接收@State装饰的变量,会出现编译和编辑报错 859 ChildPage({ ChildBuilder: this.message }) 860 } 861 } 862} 863 864@Component 865struct ChildPage { 866 @BuilderParam ChildBuilder: () => void = globalBuilder; 867 868 build() { 869 Column() { 870 this.ChildBuilder() 871 } 872 } 873} 874``` 875 876使用全局`@Builder`装饰的`globalBuilder()`方法为子组件`@BuilderParam`装饰的`ChildBuilder`变量进行初始化,编译时无报错,功能正常。 877 878【正例】 879 880```ts 881@Builder function globalBuilder() { 882 Text('Hello World') 883} 884@Entry 885@Component 886struct CustomBuilderDemo { 887 build() { 888 Column() { 889 ChildPage({ChildBuilder: globalBuilder}) 890 } 891 } 892} 893 894@Component 895struct ChildPage { 896 @BuilderParam ChildBuilder: () => void = globalBuilder; 897 build() { 898 Column() { 899 this.ChildBuilder() 900 } 901 } 902} 903```