ããã«ã¡ã¯ï¼èªãæé決ãã¦ãã¿ã¾ããï¼ ãã¯ã©ã¯ç³è«ã»çµè²»ç²¾ç® ãã¤ãã£ãã¢ããªã¨ã³ã¸ãã¢ã®yoheiã§ãã
æè¿Amazonã§ã»ã¼ã«ã«ãªã£ã¦ããå°å¤ªã®å¯¿å¸ãã¤ããèªã¿ãã¦ã寿å¸ã®å¥¥æ·±ãç´ æã®é®®åº¦ã®éè¦æ§ãåèªèãããã¾ããã寿å¸è·äººã¯ãããã
ãã®è¨äºã¯LayerXããã¯ã¢ãã«ã¬2024ã®22æ¥ç®ã®è¨äºã§ãã
å æ¥ãFlutterã¢ã¼ããã¯ãã£è¨è¨ã®æåç· - 4社ãèªãå®åã§ã®ææ¦ã¨å·¥å¤« ã§è¤éãªä»æ§ã«ç«ã¡åããã¢ã¼ããã¯ã㣠ã®è©±ãããã¦ããã ãã¾ããã
ã¢ã¼ã«ã¤ãåç»ãããã®ã§ãã²å¾¡è¦§ãã ããã
ä»åã¯è¤éãªä»æ§ã«ç«ã¡åããããã«ã©ã®ãããªå®è£ ããã¦ããããæ¸ãããã¨ãããã¾ãã
ãªãè¤éãªä»æ§ãåé¡ã«ãªãã®ã
ãã¯ã©ã¯ã§ã¯ãããããã¡ã¤ã³ãé£ããã®ã«å ãã大å¤ãªãã¨ã¯ã·ã¹ãã ã«ä»»ãã人éã楽ã§ãããããªèãæ¹ã§éçºãé²ãã¦ãã¾ãã
ãã®ãããé£ããäºè±¡ã解決ããããã«ä»æ§ãã©ãã©ãè¤éã«ãªã£ã¦ãã¾ããã¾ããä»æ§ã¯æ¥ã æ´æ°ãããã¢ã©ã¼ããããªãã¼ã·ã§ã³ã追å ã»å¤æ´ããç¶ãã¾ãã
ã¾ãã¯ã¨ã¦ãåç´ãªãµã³ãã«ã§ããç§ãã¡ãéçºãã¦ããç³è«çµè²»ç²¾ç®ã®ã¢ããªã®å®éã®ç»é¢ã§ãã
çµè²»ç²¾ç®ã«ãããæç´°ã®éé¡ã¯ä»¥ä¸ã®2ãã¿ã¼ã³ãåããã¨ãã§ãã¾ãã
- èªç±å ¥åï¼ç·¨éå¯ï¼
- æå½ãªã©ã«ããè¨ç®ããèªåå ¥åï¼ç·¨éä¸å¯ï¼
ãã®ä»æ§ãæºããããã«å¿ è¦ãªãã©ã¡ã¼ã¿ã¼ã¯ä»¥ä¸ã®2ã¤ã«ãªãããªã¨æãã¾ãã
- éé¡å ¥åå¤
- ç·¨éå¯ãã©ããã®ãã©ã°
å®éã«Dartã®ã³ã¼ãã§æ¸ãã¨ä»¥ä¸ã®ããã«ãªãã¾ãã
class PaymentAmountState { /// éé¡å ¥åå¤ final int input; /// ç·¨éå¯è½ãã©ãã final bool isEditable; }
å®éã«Formã表ç¾ããã¨ä»¥ä¸ã®ããã«ãªãã¾ãã
final controller = useTextEditingController(text: paymentAmountState.input); TextField( controller: controller, readOnly: !paymentAmountState.isEditable, // onChangeãªã© );
ãã®æ®µéã§ã¯é常ã«ã·ã³ãã«ãªå®è£ ã§æ¸ã¿ã¾ããããããæ°ããä»æ§ã追å ãããã¨ãç¶æ³ã¯è¤éã«ãªã£ã¦ããã¾ãã ä¾ãã°ããã¯ã©ã¯ã§ã¯ã¬ã·ã¼ããªã©è¨¼æç»åãã¢ãããã¼ãããã¨ãAIãOCRãå®è¡ãæç´°ã®éé¡ãèªåã§å ¥åãã¦ãããæ©è½ãããã¾ãã 追å ã®ä»æ§ã§ãAI-OCRããéé¡ãèªã¿åãããã¨ãã«ã¯éé¡ã®æ¨ªã«ããã¸ã表示ããããAIãå¤ãããããã¨ããããããã«ãããï¼ç·¨éå¯ï¼ã¨ãªãã¾ããããã®ãããªå ´åãã©ã®ããã«å®è£ ããã°ããã§ããããï¼
åç´ã«ãã©ã°ã追å ããã¨ãã®ããã«ãªãã¾ãã
class PaymentAmountState { /// éé¡å ¥åå¤ final int input; /// ç·¨éå¯è½ãã©ãã final bool isEditable; /// AIã«ããå¤ãå ¥åããã final bool filledByAi; }
ããã ã¨ãä»æ§ä¸ããããªããAIãå ¥åããå ´åã«ç·¨éä¸å¯ããªç¶æ ãä½ãã¦ãã¾ãã¾ãã ãããã®ããããªãå¤ãèæ ®ããããã§ã®ãã³ããªã³ã°ãå¿ è¦ã«ãªãä¸ãæ°ããéçºè ãå ¥ã£ãã¨ãã«æ¯åãAIãå ¥åããå ´åã«ç·¨éå¯ãã¨ãã説æãå¿ è¦ã«ãªããä»æ§ãã³ã¼ãä¸ã§è¡¨ç¾ã§ãã¦ãã¾ããã
ãããªã¨ãã«ä½¿ãã®ãSealed classã§ãã
Sealed classã¨ã¯
Sealed classã¨ã¯ä½ããChatGPTããã«èãã¾ããã
Sealed classã¯ãDart 3ã§æ£å¼ã«å°å ¥ããã æ°ããã¯ã©ã¹ä¿®é£¾åã§ãã¯ã©ã¹ã®ç¶æ¿é¢ä¿ãå³å¯ã«ç®¡çãããã¨ãã§ãã¾ããããã«ããããã¡ã¤ã³ä¸ã®ç¹å®ã®ç¶æ ãããªã¨ã¼ã·ã§ã³ããæ¼ããªãããå®ç¾©éãã«ã表ç¾ãããããªãã¾ãã
Sealed classã®ãã¤ã³ã
ç¶æ¿é¢ä¿ã®å¶ç´
Sealed classã¯ãåä¸ã©ã¤ãã©ãªå ã§ã®ã¿ãµãã¯ã©ã¹åã許å¯ããã¦ãã¾ããã¤ã¾ããSealedã¯ã©ã¹ãç¶æ¿ã§ããã¯ã©ã¹ã¯ãå®ç¾©å ã¨åããã¡ã¤ã«ãã¾ãã¯åãã©ã¤ãã©ãªå ã«éããã¾ããããã«ãããæ³å®å¤ã®ã¯ã©ã¹ãå¤é¨ããèªç±ã«ç¶æ¿ãããã¨ãé²ããç¶æ ãããªã¨ã¼ã·ã§ã³ãå³å¯ã«ã³ã³ããã¼ã«ãããã¨ãå¯è½ã«ãªãã¾ãã
ãã¿ã¼ã³ãããã³ã°ã¨ã®çµã¿åããã§å¼·åãªã¨ã©ã¼ãã§ãã¯
Sealedã¯ã©ã¹ã¨ãµãã¯ã©ã¹ã«ãã£ã¦å®ç¾©ãããç¶æ ã¯ã
switch
ãwhen
æã§ç¶²ç¾ çã«ãã§ãã¯ã§ãã¾ããããã«ãããéçºè ã¯ãèæ ®æ¼ããããªããã¨ãã³ã³ãã¤ã«æã«ä¿è¨¼ã§ãã¾ããä¾ãã°ã
Result
ã¨ããSealedã¯ã©ã¹ãSuccess
ãError
ãLoading
ã¨ãã3ã¤ã®ãµãã¯ã©ã¹ãæã£ã¦ããå ´åãswitch
ã§Result
ãåå²ããéãããã3ã±ã¼ã¹ãã¹ã¦ããã³ããªã³ã°ããªãã¨ã³ã³ãã¤ã©ãè¦åãåºãã¾ããenumã¨ç°ãªãæè»æ§
enumã¯ç¶æ ãå®æ°å¤ã®éåã表ãã®ã«åãã¦ãã¾ãããenumèªä½ã¯å¤ãä¿æãããã¨ã¯å¯è½ã§ããè¤éãªãã¸ãã¯ãè¤æ°ã®ããããã£ãå å ããã«ã¯ããéå®çã§ãã
ä¸æ¹ã§Sealedã¯ã©ã¹ã¯ãã¯ã©ã¹ãã§ããããããã£ã¼ã«ããã¡ã½ãããªã©ã®è¤éãªãã¸ãã¯ããã¼ã¿ãæããããã¨ãã§ãã¾ãã
ã¾ããè¤æ°ã®Sealedã¯ã©ã¹ãµãã¿ã¤ãã§ç°ãªãåã®æ å ±ãä¿æããç°ãªãæ¯ãèããå®è£ ãããã¨ãå¯è½ã¨ãªãããããªãããªç¶æ 表ç¾ãã§ãã¾ãã
ãã¡ã¤ã³ãã¸ãã¯è¡¨ç¾ã®æ確å
Sealedã¯ã©ã¹ãæ´»ç¨ããã¨ãã¢ããªã±ã¼ã·ã§ã³åºæã®ãã¡ã¤ã³ç¶æ ï¼ã¨ã©ã¼ç¶æ ããã¼ã¿åå¾ç¶æ³ãã¦ã¼ã¶ã¼æä½ã¹ãã¼ã¿ã¹ãªã©ï¼ãåã¬ãã«ã§æ示ããã³ã³ãã¤ã«æã«æ£ããå¦çããã¦ããããä¿è¨¼ã§ãã¾ãã
ããã«ãã£ã¦å®è¡æã¨ã©ã¼ãç¶æ ã®ä¸æ´åãæªç¶ã«é²ããã¨ãã§ããã³ã¼ãã£ã³ã°æç¹ã§ç¶²ç¾ æ§ã»æ´åæ§ã確ä¿ãããã¨ãå¯è½ã§ãã
ã¾ãã«4çªãä»åã®ã±ã¼ã¹ã«å½ã¦ã¯ã¾ãã¾ããã
Sealed classã使ã£ã¦æ¹å
å ç¨ã®ãã¡ãã®ã³ã¼ããSealed classã使ã£ã¦æ¹åãããã¨æãã¾ãã
// Before class PaymentAmountState { /// éé¡å ¥åå¤ final int input; /// ç·¨éå¯è½ãã©ãã final bool isEditable; /// AIã«ããå¤ãå ¥åããã final bool filledByAi; }
æ¹åå¾ã¯ãã¡ãã«ãªãã¾ãã
//After sealed class PaymentAmountState { PaymentAmountState(this.input); /// éé¡å ¥åå¤ final int input; bool get isEditable; } /// æå ¥å ç·¨éå¯ class ManualInputPaymentAmountState extends PaymentAmountState { ManualInputPaymentAmountState(super.input); @override bool get isEditable => true; } /// èªåå ¥å ç·¨éä¸å¯ class AutoFillPaymentAmountState extends PaymentAmountState { AutoFillPaymentAmountState(super.input); @override bool get isEditable => false; } /// AIã«ããèªã¿åããã class FilledByAiPaymentAmountState extends PaymentAmountState { FilledByAiPaymentAmountState(super.input); @override bool get isEditable => true; }
ããã«ããä»æ§ãæºããã³ã¼ãã表ç¾ã§ãããã¨ã«ãªãã¾ãã
PaymentAmountState
ã¯ManualInputPaymentAmountState
, AutoFillPaymentAmountState
, FilledByAiPaymentAmountState
ã®3ã¤ã®ç¶æ
ãåããã¨ãã§ããããããç·¨éå¯è½ãã©ãããã¯ã©ã¹ãã¿ãã¨ãããã¾ãã
æ´ã«AIã«ããèªã¿åãããå ´åã«ã¯ä»ã«èªã¿åããåè£ã®å¤ã表示ããããªã©ã®ä»æ§ã追å ã«ãªã£ãã¨ãã¦ãFilledByAiPaymentAmountState
ã«ä»ã®é¸æè¢ããããããã¨ãã§ãã¾ããï¼ãã®ã¯ã©ã¹ã«æãããã®ãæ£ããã®ãã¯å¥ã¨ãã¦ð
ï¼
class FilledByAiPaymentAmountState extends PaymentAmountState { FilledByAiPaymentAmountState(super.input); /// AIã«ããèªã¿åãããå¤ã®é¸æåè£ã®æ°å¤ final List<int> candidates; @override bool get isEditable => true; }
æ´ã«Sealed classã®ããã¨ããã¨ãã¦ããã¿ã¼ã³ããããããã¾ãã
ãã¯ã©ã¯ã§ã¯å¤è²¨å¯¾å¿ããã¦ãããæ¥æ¬åã®ã¿å ¥åã®å ´åã¨å¤è²¨å ¥åãå¯è½ãªéé¡ãã©ã¼ã ãä½ããã¨ãã§ãã¾ãã
ãã®å ´åã®éé¡ã¯ä»¥ä¸ã®ããã«Sealedã¯ã©ã¹ã使ã£ã¦å®è£ ãã¦ãã¾ãã
/// éé¡ sealed class PaymentAmount {} /// æ¥æ¬åã®ã¿ class JpyPaymentAmount implements PaymentAmount { /// æ¥æ¬å final int amount; } /// æ¥æ¬å+å¤è²¨ class ForexPaymentAmount implements PaymentAmount { /// å¤è²¨ã³ã¼ã final String currencyCode; /// å ¥åãããéé¡ final double amount; /// æ¥æ¬åã«å¤æããã¬ã¼ã final double rate; }
éé¡ãAPIã«éåºããå ´åã«switchæã§ãã¿ã¼ã³ããããè¡ããã©ã¡ã¼ã¿ã¼ä½ã£ã¦ã¾ãã
PaymentAmountParameter createParameter(PaymentAmount paymentAmount) { return switch(paymentAmount) { JpyPaymentAmount(:final amount) => PaymentAmountParameter.jpy(amount), ForexPaymentAmount(:final amount, :final currencyCode, :final rate) => PaymentAmountParameter.forex(amount, currencyCode, rate), }; }
ãã¿ã¼ã³ããããå¼·åãªç¹ã¯å ¨ã±ã¼ã¹ãç¶²ç¾ ããªãéãã³ã³ãã¤ã«ã¨ã©ã¼ãåºããããä»æ§å¤æ´æã«æ°ããç¶æ ã追å ãã¦ãæ¼ãããªããªãç¹ã§ãã
ä¾ãã°ãå¤è²¨ã§ã¬ã¼ãã¯ãªãå¤è²¨ã¨æ¥æ¬åãåºå®ã®ã±ã¼ã¹ã追å ã¨ãªã£ãå ´åãAPIãã©ã¡ã¼ã¿ã¼ä½æã®é¢æ°ãã¨ã©ã¼ã«ãªãã¾ããéçºè ã¯ãã¿ã¼ã³è¿½å ã«ããå½±é¿ç¯å²ãç¥ã£ã¦ããå¿ è¦ã¯ãªããã³ã³ãã¤ã«ã¨ã©ã¼ã«ãªã£ãç®æã®ä¿®æ£ãããã ãã§ãããªãã¾ãã
â»is
ã switchã®default
ã±ã¼ã¹ã使ã£ã¦ãå ´åãã³ã³ãã¤ã«ã¨ã©ã¼ã«ãªããªãã®ã§æä½éã®ãã³ããªã³ã°ã®ã¿å¿
è¦ã¨ããæ確ãªç¢ºè¨¼ããªãå ´åã¯å©ç¨ã«æ³¨æãå¿
è¦ãªããããã¹ã¦ã®ã±ã¼ã¹ã網ç¾
ãã¦æ¸ãã¦ãããã¨ããããããã¾ãã
/// å¤è²¨ã¨æ¥æ¬åãåºå® class FixedForexPaymentAmount implements PaymentAmount { /// å¤è²¨ã³ã¼ã final String currencyCode; /// å¤è²¨éé¡ final double forexAmount; /// æ¥æ¬å final int jpyAmount; } PaymentAmountParameter createParameter(PaymentAmount paymentAmount) { // `FixedForexPaymentAmount`ã®caseã追å ããªãã¨ã³ã³ãã¤ã«ã¨ã©ã¼ã«ãªã return switch(paymentAmount) { JpyPaymentAmount(:final amount) => PaymentAmountParameter.jpy(amount), ForexPaymentAmount(:final amount, :final currencyCode, :final rate) => PaymentAmountParameter.forex(amount, currencyCode, forexAmount), FixedForexPaymentAmount(:final currencyCode, :final forexAmount, :final jpyAmount) => PaymentAmountParameter.fixedForex(jpyAmount, currencyCode, forexAmount), }; }
å¼·åãªSealed classããã¯ã©ã¯ã§ã¯ä»ã«ã以ä¸ã®ãããªãã¿ã¼ã³ã§ä½¿ç¨ãã¦ãã¾ãã
- ãã©ã¼ã 種å¥ã®ãã¿ã¼ã³
- æ¯æç³è«ãçµè²»ç²¾ç®ãªã©
- æç´°ã®ãã¿ã¼ã³
- æå ¥åã交éè²»ãæå½ãªã©
- æå ¥åãããè¦ç´ ãªã®ããé¸æãããè¦ç´ ãªã®ã
ã¾ã¨ã
è¤éåãããã¸ãã¹ä»æ§ã«å¯¾ãã¦ãã³ã¼ãä¸ã§ãã¡ã¤ã³ã«ã¼ã«ãç¶æ ãæ示çã«è¡¨ç¾ãããã¨ã¯ãå ç¢ãªå®è£ ã®éµã¨ãªãã¾ãã
Dart 3ã§å°å ¥ãããSealed classã¯ãããããªãç¶æ ãåã·ã¹ãã ã§é²ãããã¿ã¼ã³ãããã³ã°ã«ããç¶²ç¾ æ§ãã§ãã¯ãå¯è½ã«ãã¾ããããã«ããããã¸ãã¯æ¼ããä¸æ´åãªç¶æ ãçºçãã¥ããããå°æ¥çãªä»æ§å¤æ´ã«å¯¾ãã¦ãå¼·ãèæ§ãæã¤ã³ã¼ããæ¸ããã¨ãã§ãã¾ã
ããããåã¬ãã«ã®è¡¨ç¾ã¯ãä¿å®æ§ã»å¯èªæ§ãé«ãããã¼ã å ã®å ±éç解ããµãã¼ããã¾ã¾ããçµæã¨ãã¦ããã°ãä»æ§æ¼ãã®æ¸å°ããªãã¡ã¯ã¿ãªã³ã°ã®å®¹æåãè¿ éãªä»æ§å¤æ´ã¸ã®å¯¾å¿ãªã©ãé·æçãªå質ã¨éçºå¹çåä¸ããã¦ããã¾ãã
çµããã«
ã¢ãã¤ã«éçºã«ã¤ãã¦æ°ã«ãªããã¨ãããã°ä½ã§ãã話ãã¾ãããï¼LayerXã®ã¢ããªéçºã¯ã©ããªãã¨ãã£ã¦ãã®ï¼ã§ã大ä¸å¤«ã§ãã
æ¡ç¨æ å ±ã¯ãã¡ãâ