🦁

Dart で条件を満たしたものだけが入る型を作る

2022/06/17に公開

アカウント名は前後に空白が入らずに, 1文字以上 50文字以内である必要があるとする.

そういうときに, このように条件を満たしていることを保証する型 (class) を作成することによって条件を満たしているかの確認し忘れが減る.

account_name.dart
import 'package:meta/meta.dart';

/// アカウント名. 文字数条件を満たしていることを保証される

class AccountName {
  final String value;

  const AccountName._(this.value);

  /// `String` からアカウント名を作成する. 条件を満たしていないものは `null` が返される
  static AccountName? fromString(final String raw) {
    final trimmed = raw.trim();
    if (trimmed.isEmpty || trimmed.length >= 50) {
      return null;
    }
    return AccountName._(trimmed);
  }

  /// String` からアカウント名を作成する. 条件を満たしていないものが渡されたときにはエラーが発生する
  static AccountName fromStringOrThrow(final String raw) {
    final normalized = fromString(raw);
    if (normalized == null) {
      throw Exception("$raw is invalid account name");
    }
    return normalized;
  }

  
  bool operator ==(final Object other) {
    return other is AccountName && value == other.value;
  }

  
  int get hashCode => value.hashCode;

  
  String toString() {
    return "AccountName($value)";
  }
}

解説

const AccountName._(this.value);

の部分で, private constructor を作成しているため, 外部のファイルから AccountName を直接作成することはできなくなっている

use.dart
import 'account_name.dart';

void main() {
  final rafyaAccountName = AccountName("rafya");
}

error

このように使う

import 'account_name.dart';

void main() {
  final rafyaAccountName = AccountName.fromString("rafya");
  if (rafyaAccountName == null) {
    print("不正なアカウント名です");
    return;
  }
  print(rafyaAccountName.value); // rafya
}
GitHubで編集を提案

Discussion