Dartのオブジェクト指向プログラミングについて学ぶ
オブジェクト指向プログラミング
よく聞くオブジェクト指向プログラミング これには3つの大きな柱があります
- ポリモーフィズム(多様性)
- 継承
- カプセル化
ポリモーフィズムだけわからない😅
調べてみた🔍
ポリモーフィズムとは、日本語で「多様性」「多態性」「多相性」と訳すことができます。
と紹介されていた🤔
継承とは?
親クラスのデータを子供のクラスが持っている。そんなイメージ?
カプセル化とは?
外部からの変更をできないようにすることです。(オブジェクトの隠蔽)と表現される。
Dartは、変数の先頭に_をつける。Javaだと変数にPrivateをつける。これで、隠蔽をすることができる。
以前書いていたQiitaの記事がございます。綺麗な記事ではないですが、参考までに載せておきます😅
新しくクラスを作ってみた。機能も新たに作成。すごく単純なものですが...
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の文法を理解してくるとソースコードが読めるようになってきます。
日本語のサイトでわかりやすいサイトがありました。
Discussion