🏤

Dart3.0から追加されたextension typeを使ってみる

2024/06/12に公開

対象者

Dart3.0から追加されたextension typeなるものがあるそうです。

これな

extension type E(int i) {
  // Define set of operations.
}

昔からあるもの

extension NumberParsing on String {
  int parseInt() {
    return int.parse(this);
  }
  // ···
}

公式を日本語に翻訳して解説したものもありますのでよかったら見てみてください。コンストラクタつけられるみたいです?
https://zenn.dev/joo_hashi/books/d474838414a840/viewer/4adea6

プロジェクトの説明

昔は、ロジックを書いたクラスを作って、正規表現を使っていたのですが、extension typeだとメソッドを書いてる感じでかけるので、分かりやすいかも?

ひらがなとカタカナだけ入力できるvalidationを作ってみました!

  1. extension typeを作成
// ひらがなと英語数字で入力されているとエラーを出す
extension type Hiragana(String hiragana) implements String {
  // ひらがなと英語数字で入力されているとエラーを出す
  bool isHiragana() => hiragana.contains(RegExp('[ぁ-んa-zA-Z0-9]'));
}
  1. Stateクラスで状態を管理する
class _ExtensionFormState extends State<ExtensionForm> {

  String hiraganaErrText = '';
  String katakanaErrText = '';

  void _validateHiragana(String hiragana) {
    final text = Hiragana(hiragana);
    if (text.isHiragana()) {
      setState(() {
        hiraganaErrText = 'カタカナで入力してください!';
      });
    } else {
      setState(() {
        hiraganaErrText = '';
      });
    }
  }

  void _validateKatakana(String katakana) {
    final text = Katakana(katakana);
    if (text.isKatakana()) {
      setState(() {
        katakanaErrText = 'ひらがなで入力してください!';
      });
    } else {
      setState(() {
        katakanaErrText = '';
      });
    }
  }
  1. 入力フォームで正規表現のエラーチェックをする
TextFormField(
              onChanged: _validateHiragana,
              decoration: const InputDecoration(
                labelText: 'カタカナ以外だめ',
              ),
            ),
            if (hiraganaErrText.isNotEmpty)
              Text(
                hiraganaErrText,
                style: const TextStyle(color: Colors.red),
              ),
import 'package:flutter/material.dart';

// ひらがなと英語数字で入力されているとエラーを出す
extension type Hiragana(String hiragana) implements String {
  // ひらがなと英語数字で入力されているとエラーを出す
  bool isHiragana() => hiragana.contains(RegExp('[ぁ-んa-zA-Z0-9]'));
}

// カタカナで入力されているとエラーを出す
extension type Katakana(String katakana) implements String {
  bool isKatakana() => katakana.contains(RegExp('[ァ-ンa-zA-Z0-9]'));
}

class ExtensionForm extends StatefulWidget {
  const ExtensionForm({super.key});

  
  State<ExtensionForm> createState() => _ExtensionFormState();
}

class _ExtensionFormState extends State<ExtensionForm> {

  String hiraganaErrText = '';
  String katakanaErrText = '';

  void _validateHiragana(String hiragana) {
    final text = Hiragana(hiragana);
    if (text.isHiragana()) {
      setState(() {
        hiraganaErrText = 'カタカナで入力してください!';
      });
    } else {
      setState(() {
        hiraganaErrText = '';
      });
    }
  }

  void _validateKatakana(String katakana) {
    final text = Katakana(katakana);
    if (text.isKatakana()) {
      setState(() {
        katakanaErrText = 'ひらがなで入力してください!';
      });
    } else {
      setState(() {
        katakanaErrText = '';
      });
    }
  }
  

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Email Checker'),
      ),
      body: Form(
        child: Column(
          children: [
            TextFormField(
              onChanged: _validateHiragana,
              decoration: const InputDecoration(
                labelText: 'カタカナ以外だめ',
              ),
            ),
            if (hiraganaErrText.isNotEmpty)
              Text(
                hiraganaErrText,
                style: const TextStyle(color: Colors.red),
              ),
            TextFormField(
              onChanged: _validateKatakana,
              decoration: const InputDecoration(
                labelText: 'ひらがな以外だめ',
              ),
            ),
            if (katakanaErrText.isNotEmpty)
              Text(
                katakanaErrText,
                style: const TextStyle(color: Colors.red),
              ),
            ElevatedButton(
              onPressed: () {
                debugPrint('Submit');
              },
              child: const Text('Submit'),
            ),
          ],
        ),
      ),
    );
  }
}

実行するコード:

main.dart
import 'package:flutter/material.dart';
import 'package:widget_cookbook/extention_form/extension_form.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: ExtensionForm(),
    );
  }
}

こんな感じで動きます

英語と数字の入力も受け付けないようになってます。StatefulWidtget使ってるので、画面の更新がされるたびに、全体が再描画されるのが心配ですが😅


感想

今回は、 Dart3.0から追加されたextension type を使ってみました。他にも使い道ありそうだから、色々試してみたい。検索してもいつもサンプルコードしか出てこないのが悩み💦

Discussion