1# 自定义组件成员属性访问限定符使用限制
2
3在状态管理V1中,当组件开发者封装了自定义组件后,由于组件没有明确的输入输出标识,使得调用方无法按照统一的标准判断传入哪些变量作为组件入参。在状态管理V1中,可以使用private限定符来限制当前变量不允许被进行外部初始化。
4
5当组件开发者不希望状态变量被外部初始化时,可以添加private限定符,提醒组件调用方不要初始化该状态变量。但是外部初始化也需要遵循装饰器自身的规则,具体规则见[使用限制](#使用限制)。
6
7ArkTS会对自定义组件的成员变量使用的访问限定符private/public/protected进行校验,当不按规范使用访问限定符private/public/protected时,会产生对应的日志信息。
8
9在阅读本文档前,建议提前阅读:[状态管理概述](./arkts-state-management-overview.md)。
10
11> **说明:**
12>
13> 从API version 12开始,支持自定义组件成员属性访问限定符使用限制的规则。
14
15
16## 使用限制
17
18- [\@State](./arkts-state.md)/[\@Prop](./arkts-prop.md)/[\@Provide](./arkts-provide-and-consume.md)/[\@BuilderParam](./arkts-builderparam.md)/常规成员变量(不涉及更新的普通变量)的初始化规则为可以被外部初始化,也可以使用本地值进行初始化。当组件开发者不希望当前变量被外部初始化时,可以使用private进行修饰,此时会有编译告警日志提示。
19
20- [\@StorageLink](./arkts-appstorage.md)/[\@StorageProp](./arkts-appstorage.md)/[\@LocalStorageLink](./arkts-localstorage.md)/[\@LocalStorageProp](./arkts-localstorage.md)/[\@Consume](./arkts-provide-and-consume.md)变量的初始化规则为不可以被外部初始化,当组件开发者希望当前变量被外部初始化而使用public修饰时,这和装饰器本身的初始化规则是相违背的,会有编译告警日志提示。
21
22- [\@Link](./arkts-link.md)/[\@ObjectLink](./arkts-observed-and-objectlink.md)变量的初始化规则为必须被外部初始化,禁止本地初始化。当组件开发者使用private对变量进行修饰时,这和装饰器本身的初始化规则相矛盾,会有编译告警日志提示。
23
24- 由于struct没有继承能力,上述所有的这些变量使用protected修饰时,会有编译告警日志提示。
25
26- [\@Require](./arkts-require.md)含义是当前被\@Require装饰的变量必须被外部初始化,当\@Require和private同时装饰[\@State](./arkts-state.md)/[\@Prop](./arkts-prop.md)/[\@Provide](./arkts-provide-and-consume.md)/[\@BuilderParam](./arkts-builderparam.md)/常规成员变量(不涉及更新的普通变量)时,他们的含义是自相矛盾的,会有编译告警日志提示。
27
28
29## 使用场景
30
311.当成员变量被private访问限定符和\@State/\@Prop/\@Provide/\@BuilderParam装饰器同时修饰,并且通过父组件进行初始化赋值,ArkTS会进行校验并产生告警日志。
32
33【反例】
34```ts
35@Entry
36@Component
37struct AccessRestrictions {
38  @Builder
39  buildTest() {
40    Text("Parent builder")
41  }
42
43  build() {
44    Column() {
45      ComponentsChild({
46        state_value: "Hello",
47        prop_value: "Hello",
48        provide_value: "Hello",
49        builder_value: this.buildTest,
50        regular_value: "Hello"
51      })
52    }
53    .width('100%')
54  }
55}
56
57@Component
58struct ComponentsChild {
59  // 此处使用private修饰符时会出现告警日志
60  @State private state_value: string = "Hello";
61  // 此处使用private修饰符时会出现告警日志
62  @Prop private prop_value: string = "Hello";
63  // 此处使用private修饰符时会出现告警日志
64  @Provide private provide_value: string = "Hello";
65  // 此处使用private修饰符时会出现告警日志
66  @BuilderParam private builder_value: () => void = this.buildTest;
67  // 此处使用private修饰符时会出现告警日志
68  private regular_value: string = "Hello";
69
70  @Builder
71  buildTest() {
72    Text("Child builder")
73  }
74
75  build() {
76    Column() {
77      Text("Hello")
78        .fontSize(50)
79        .fontWeight(FontWeight.Bold)
80    }
81  }
82}
83```
84
85编译告警日志如下:
86
87```ts
88Property 'state_value' is private and can not be initialized through the component constructor.
89Property 'prop_value' is private and can not be initialized through the component constructor.
90Property 'provide_value' is private and can not be initialized through the component constructor.
91Property 'builder_value' is private and can not be initialized through the component constructor.
92Property 'regular_value' is private and can not be initialized through the component constructor.
93```
94
95【正例】
96```ts
97@Entry
98@Component
99struct AccessRestrictions {
100  @Builder
101  buildTest() {
102    Text("Parent builder")
103  }
104
105  build() {
106    Column() {
107      ComponentsChild({
108        state_value: "Hello",
109        prop_value: "Hello",
110        provide_value: "Hello",
111        builder_value: this.buildTest,
112        regular_value: "Hello"
113      })
114    }
115    .width('100%')
116  }
117}
118
119@Component
120struct ComponentsChild {
121  @State state_value: string = "Hello";
122  @Prop prop_value: string = "Hello";
123  @Provide provide_value: string = "Hello";
124  @BuilderParam builder_value: () => void = this.buildTest;
125  regular_value: string = "Hello";
126
127  @Builder
128  buildTest() {
129    Text("Child builder")
130  }
131
132  build() {
133    Column() {
134      Text("Hello")
135        .fontSize(50)
136        .fontWeight(FontWeight.Bold)
137    }
138  }
139}
140```
141
1422.当成员变量被public访问限定符和\@StorageLink/\@StorageProp/\@LocalStorageLink/\@LocalStorageProp/\@Consume装饰器同时修饰,并且通过父组件进行初始化赋值,ArkTS会进行校验并产生告警日志。
143
144【反例】
145```ts
146@Entry
147@Component
148struct AccessRestrictions {
149  @Provide consume_value: string = "Hello";
150  build() {
151    Column() {
152      ComponentChild()
153    }
154    .width('100%')
155  }
156}
157
158@Component
159struct ComponentChild {
160  // 此处使用public修饰符时会出现告警日志
161  @LocalStorageProp("sessionLocalProp") public local_prop_value: string = "Hello";
162  // 此处使用public修饰符时会出现告警日志
163  @LocalStorageLink("sessionLocalLink") public local_link_value: string = "Hello";
164  // 此处使用public修饰符时会出现告警日志
165  @StorageProp("sessionProp") public storage_prop_value: string = "Hello";
166  // 此处使用public修饰符时会出现告警日志
167  @StorageLink("sessionLink") public storage_link_value: string = "Hello";
168  // 此处使用public修饰符时会出现告警日志
169  @Consume public consume_value: string;
170
171  build() {
172    Column() {
173      Text("Hello")
174        .fontSize(50)
175        .fontWeight(FontWeight.Bold)
176    }
177  }
178}
179```
180
181编译告警日志如下:
182
183```ts
184Property 'local_prop_value' can not be decorated with both @LocalStorageProp and public.
185Property 'local_link_value' can not be decorated with both @LocalStorageLink and public.
186Property 'storage_prop_value' can not be decorated with both @StorageProp and public.
187Property 'storage_link_value' can not be decorated with both @StorageLink and public.
188Property 'consume_value' can not be decorated with both @Consume and public.
189```
190
191【正例】
192```ts
193@Entry
194@Component
195struct AccessRestrictions {
196  @Provide consume_value: string = "Hello";
197  build() {
198    Column() {
199      ComponentChild()
200    }
201    .width('100%')
202  }
203}
204
205@Component
206struct ComponentChild {
207  @LocalStorageProp("sessionLocalProp") local_prop_value: string = "Hello";
208  @LocalStorageLink("sessionLocalLink") local_link_value: string = "Hello";
209  @StorageProp("sessionProp") storage_prop_value: string = "Hello";
210  @StorageLink("sessionLink") storage_link_value: string = "Hello";
211  @Consume consume_value: string;
212  build() {
213    Column() {
214      Text("Hello")
215        .fontSize(50)
216        .fontWeight(FontWeight.Bold)
217    }
218  }
219}
220```
221
2223.当成员变量被private访问限定符和\@Link/\@ObjectLink装饰器同时修饰,并且通过父组件进行初始化赋值,ArkTS会进行校验并产生告警日志。
223
224【反例】
225```ts
226@Entry
227@Component
228struct AccessRestrictions {
229  @State link_value: string = "Hello";
230  @State objectLink_value: ComponentObj = new ComponentObj();
231  build() {
232    Column() {
233      ComponentChild({link_value: this.link_value, objectLink_value: this.objectLink_value})
234    }
235    .width('100%')
236  }
237}
238
239@Observed
240class ComponentObj {
241  count: number = 0;
242}
243@Component
244struct ComponentChild {
245  // 此处使用private修饰符时会出现告警日志
246  @Link private link_value: string;
247  // 此处使用private修饰符时会出现告警日志
248  @ObjectLink private objectLink_value: ComponentObj;
249  build() {
250    Column() {
251      Text("Hello")
252        .fontSize(50)
253        .fontWeight(FontWeight.Bold)
254    }
255  }
256}
257```
258
259编译告警日志如下:
260
261```ts
262Property 'link_value' can not be decorated with both @Link and private.
263Property 'objectLink_value' can not be decorated with both @ObjectLink and private.
264```
265
266【正例】
267```ts
268@Entry
269@Component
270struct AccessRestrictions {
271  @State link_value: string = "Hello";
272  @State objectLink_value: ComponentObj = new ComponentObj();
273  build() {
274    Column() {
275      ComponentChild({link_value: this.link_value, objectLink_value: this.objectLink_value})
276    }
277    .width('100%')
278  }
279}
280
281@Observed
282class ComponentObj {
283  count: number = 0;
284}
285@Component
286struct ComponentChild {
287  @Link link_value: string;
288  @ObjectLink objectLink_value: ComponentObj;
289  build() {
290    Column() {
291      Text("Hello")
292        .fontSize(50)
293        .fontWeight(FontWeight.Bold)
294    }
295  }
296}
297```
298
2994.当成员变量被protected访问限定符修饰,并且通过父组件进行初始化赋值,ArkTS会进行校验并产生告警日志。
300
301【反例】
302```ts
303@Entry
304@Component
305struct AccessRestrictions {
306  build() {
307    Column() {
308      ComponentChild({regular_value: "Hello"})
309    }
310    .width('100%')
311  }
312}
313
314@Component
315struct ComponentChild {
316  // 此处使用protected修饰符时会出现告警日志
317  protected regular_value: string = "Hello";
318  build() {
319    Column() {
320      Text("Hello")
321        .fontSize(50)
322        .fontWeight(FontWeight.Bold)
323    }
324  }
325}
326```
327
328编译告警日志如下:
329
330```ts
331The member attributes of a struct can not be protected.
332```
333
334【正例】
335```ts
336@Entry
337@Component
338struct AccessRestrictions {
339  build() {
340    Column() {
341      ComponentChild({regular_value: "Hello"})
342    }
343    .width('100%')
344  }
345}
346
347@Component
348struct ComponentChild {
349  regular_value: string = "Hello";
350  build() {
351    Column() {
352      Text("Hello")
353        .fontSize(50)
354        .fontWeight(FontWeight.Bold)
355    }
356  }
357}
358```
359
3605.当成员变量被private访问限定符、\@Require和\@State/\@Prop/\@Provide/\@BuilderParam装饰器同时修饰,并且通过父组件进行初始化赋值,ArkTS会进行校验并产生告警日志。
361
362【反例】
363```ts
364@Entry
365@Component
366struct AccessRestrictions {
367  build() {
368    Column() {
369      ComponentChild({prop_value: "Hello"})
370    }
371    .width('100%')
372  }
373}
374@Component
375struct ComponentChild {
376  // 此处使用private修饰符时会出现告警日志
377  @Require @Prop private prop_value: string = "Hello";
378  build() {
379    Column() {
380      Text("Hello")
381        .fontSize(50)
382        .fontWeight(FontWeight.Bold)
383    }
384  }
385}
386```
387
388编译告警日志如下:
389
390```ts
391Property 'prop_value' can not be decorated with both @Require and private.
392Property 'prop_value' is private and can not be initialized through the component constructor.
393```
394
395【正例】
396```ts
397@Entry
398@Component
399struct AccessRestrictions {
400  build() {
401    Column() {
402      ComponentChild({prop_value: "Hello"})
403    }
404    .width('100%')
405  }
406}
407@Component
408struct ComponentChild {
409  @Require @Prop prop_value: string = "Hello";
410  build() {
411    Column() {
412      Text("Hello")
413        .fontSize(50)
414        .fontWeight(FontWeight.Bold)
415    }
416  }
417}
418```
419