🙄

Dartのオブジェクト指向プログラミングについて学ぶ

2022/04/26に公開

オブジェクト指向プログラミング

よく聞くオブジェクト指向プログラミング これには3つの大きな柱があります

  • ポリモーフィズム(多様性)
  • 継承
  • カプセル化

ポリモーフィズムだけわからない😅

調べてみた🔍
ポリモーフィズムとは、日本語で「多様性」「多態性」「多相性」と訳すことができます。
と紹介されていた🤔

継承とは?
親クラスのデータを子供のクラスが持っている。そんなイメージ?

カプセル化とは?
外部からの変更をできないようにすることです。(オブジェクトの隠蔽)と表現される。
Dartは、変数の先頭に_をつける。Javaだと変数にPrivateをつける。これで、隠蔽をすることができる。

以前書いていたQiitaの記事がございます。綺麗な記事ではないですが、参考までに載せておきます😅
https://qiita.com/JunichiHashimoto/items/6debf988f1c09d4ebd13

新しくクラスを作ってみた。機能も新たに作成。すごく単純なものですが...

user.dart

void main() {
  var user = User(1, 'Kboyさん', '日本', '北海道', '札幌市');
  var second = secondUser(2, 'Jboyさん', '日本', '福岡県', '福岡市');
  user.prefChange = "東京都";
  user.addressChange = "恵比寿のFlutterハウス";
  second.prefChange = "神奈川県";
  second.addressChange = "横浜市";
  print('Kboyさんは' + user._prefectures + 'に滞在中です。');
  print('Kboyさんは' + user._address + 'に宿泊しています。');
  print('Jboyさんは' + second._prefectures + 'に滞在中です。');
  print('Jboyさんは' + second._address + 'のホテルニューグランドに宿泊しています。');
}

class User {
  int id;
  String name;
  String country;
  String _prefectures;
  String _address;
  // コンストラクター(初期値)
  User(this.id, this.name, this.country, this._prefectures, this._address) {
    readData();
  }
  // カプセル化の変数を取得する
  String get prefectures => _prefectures;
  String get address => _address;

  // カプセル化の変数を変更する
  set prefChange(String prefectures) => _prefectures = prefectures;
  set addressChange(String address) => _address = address;

  // インスタンス生成時に実行したい処理を指定
  void readData() {
    print("ユーザーidは$idです。");
    print("お名前は$nameです。");
    print("住んでる国は$countryです。");
    print("お住まいは、$_prefecturesです。");
    print("住所は、$_address○丁目△番地です。");
  }
}

// Userクラスを継承したsecondUserクラスを定義
class secondUser extends User {
  // 「super」を使えば親クラスのコンストラクタ・プロパティ・メソッドを継承クラスで呼び出して使用できます。
  secondUser(
      int id, String name, String country, String prefectures, String address)
      : super(id, name, country, prefectures, address);
}

実行結果

ユーザーidは1です。
お名前はKboyさんです。
住んでる国は日本です。
お住まいは、北海道です。
住所は、札幌市○丁目△番地です。
ユーザーidは2です。
お名前はJboyさんです。
住んでる国は日本です。
お住まいは、福岡県です。
住所は、福岡市○丁目△番地です。
Kboyさんは東京都に滞在中です。
Kboyさんは恵比寿のFlutterハウスに宿泊しています。
Jboyさんは神奈川県に滞在中です。
Jboyさんは横浜市のホテルニューグランドに宿泊しています。
Exited

_を変数につけるとプライベイトになり、外部からアクセスできなくなり、そのクラスの中でしか使えません。しかし、getで値を取得して、setで値を変更することができます。

なぜ、ゲッター、セッターを使うのか?、それは安全に操作するためです。外部から操作できてしますと危険ですものね😅

やってみた感想

プログラミング言語でよく聞くオブジェクト指向。「 なにそれ?、難しそう😵‍💫 」
やってることは単純でした。クラスは設計図と表現される。この中にプログラムで使う。変数(プロパティ)、関数(メソッド)を入れておいて、他のクラスでも使いたいときは、継承という機能を使って使いまわす。

Providerのコードをみたらなんとなく意味が理解できるようになっていた!

main.dart

// ignore_for_file: public_member_api_docs, lines_longer_than_80_chars
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

/// This is a reimplementation of the default Flutter application using provider + [ChangeNotifier].

void main() {
  runApp(
    /// Providers are above [MyApp] instead of inside it, so that tests
    /// can use [MyApp] while mocking the providers
    MultiProvider(
      providers: [
        ChangeNotifierProvider(create: (_) => Counter()),
      ],
      child: const MyApp(),
    ),
  );
}

/// Mix-in [DiagnosticableTreeMixin] to have access to [debugFillProperties] for the devtool
// ignore: prefer_mixin
class Counter with ChangeNotifier, DiagnosticableTreeMixin {
  int _count = 0;

  int get count => _count;

  void increment() {
    _count++;
    notifyListeners();
  }

  /// Makes `Counter` readable inside the devtools by listing all of its properties
  
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(IntProperty('count', count));
  }
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

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

class MyHomePage extends StatelessWidget {
  const MyHomePage({Key? key}) : super(key: key);

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Example'),
      ),
      body: Center(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          mainAxisAlignment: MainAxisAlignment.center,
          children: const <Widget>[
            Text('You have pushed the button this many times:'),

            /// Extracted as a separate widget for performance optimization.
            /// As a separate widget, it will rebuild independently from [MyHomePage].
            ///
            /// This is totally optional (and rarely needed).
            /// Similarly, we could also use [Consumer] or [Selector].
            Count(),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        key: const Key('increment_floatingActionButton'),

        /// Calls `context.read` instead of `context.watch` so that it does not rebuild
        /// when [Counter] changes.
        onPressed: () => context.read<Counter>().increment(),
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}

class Count extends StatelessWidget {
  const Count({Key? key}) : super(key: key);

  
  Widget build(BuildContext context) {
    return Text(

        /// Calls `context.watch` to make [Count] rebuild when [Counter] changes.
        '${context.watch<Counter>().count}',
        key: const Key('counterState'),
        style: Theme.of(context).textTheme.headline4);
  }
}

「あっ!」ゲッターが使われている。
「@override」は、親クラスのプロパティ、メソッドを変更している。
Dartの文法を理解してくるとソースコードが読めるようになってきます。

日本語のサイトでわかりやすいサイトがありました。
https://flutternyumon.com/dart-how-to-use-class/

Discussion