「関数・メソッド」について改めて考えてみるLT
#LT
「関数・メソッド」の違いは?
Ninja.icon
関数 : 処理のまとまり
メソッド : オブジェクト指向における「操作」を定義したもの
私は言語ごとに違うみたいにも聞いたことがあったbeeeyan.icon
会社員とフリーランスの違いと説明しているサイトもあった。
参考
https://wa3.i-3-i.info/diff97function.html
関数とメソッドの違いを知って、正しく使い分けよう
以降のソースコードはDartで記載しており、https://dartpad.dev/? で試せます。
関数
構成要素
戻り値・引数
code:sample1.dart
double areaFromBaseHeight(double base, double height) {
return base * height * 1/2;
}
Ninja.icon
戻り値の型 : double
baseの型 : double heightの型 : double
横道
アロー関数
code:sample2.dart
double areaFromBaseHeightAllow(double base, double height) => base * height * 1/2;
※ 分からなくなったら、段階的に考えるべき。
アロー関数式
メリット
簡潔に記述できる
積極的に使っているbeeeyan.icon
記述量が減って、読みやすい面はある。
流行り・業界の動向のような観点から、書ける・読める必要はある。
code:button.dart
IconButton(
onPressed: () => Navigator.pop(context),
icon: const Icon(
Icons.arrow_back_ios_rounded,
size: 10,
),
),
ただ、改めて調べた感じは複雑な処理に対して無理にアロー関数にしなくてもいいとは思う。
Dartの場合はonPressedの中身が二行とかになると、「=>」はつかわない。
GPT先生
Dartのアロー関数(=>)は単一の式のみに適用可能です。複数行の処理を必要とする場合、通常の関数定義({}を使用)が必要です。
引数について
https://www.geogebra.org/graphing?lang=ja
結果はxに依存している
メソッド(オブジェクト指向)の有用な点は??
例)BMI・標準体重・1日に必要な適正エネルギー(基礎代謝量)を計算する関数があったとする。
参考情報
https://sendai.tokushukai.jp/20180831-01/
code:sample3.dart
// weight : kq, height : cm
// BMIを計算するメソッド
double calculateBMI(double weight, double height) {
return weight / ((height / 100) * (height / 100));
}
// 標準体重を計算するメソッド
double calculateIdealWeight(double height) {
return 22 * ((height / 100) * (height / 100));
}
// 1日に必要な適正エネルギー(基礎代謝量)を計算するメソッド
// ここでは簡単に、体重×24を基礎代謝量としています
double calculateDailyEnergyNeeds(double weight) {
return weight * 24;
}
身長170cm、体重60kgのAさん
身長160cm、体重70kgのBさん
それぞれの値を、上記の関数で求めようとするとどうなるか?
code:main1.dart
void main() {
final bmi = calculateBMI(60, 170);
final idealWeight = calculateIdealWeight(170);
final dailyEnergyNeeds = calculateIdealWeight(60);
print('AさんのBMI $bmi');
print('Aさんの標準体重 $idealWeight');
print('Aさんの1日に必要な適正エネルギー $dailyEnergyNeeds');
print('-------------------');
final bmi2 = calculateBMI(70, 160);
final idealWeight2 = calculateIdealWeight(160);
final dailyEnergyNeeds2 = calculateIdealWeight(70);
print('BさんのBMI $bmi2');
print('Bさんの標準体重 $idealWeight2');
print('Bさんの1日に必要な適正エネルギー $dailyEnergyNeeds2');
}
面倒くさくない?? Ninja.icon
AさんBさんの身長・体重は変わっていないのにいちいち引数を設定しないといけない
身長・体重 → 人ごとに決まった情報
「人」単位で情報と処理をまとめたものを作ればいいのでは?
Userクラスの登場
code:user.dart
class User {
double height; // cm
double weight; // kg
User(this.height, this.weight);
// BMIを計算するメソッド
double calculateBMI() {
return weight / ((height / 100) * (height / 100));
}
// 標準体重を計算するメソッド
double calculateIdealWeight() {
return 22 * ((height / 100) * (height / 100));
}
// 1日に必要な適正エネルギー(基礎代謝量)を計算するメソッド
// ここでは簡単に、体重×24を基礎代謝量としています
double calculateDailyEnergyNeeds() {
return weight * 24;
}
}
これこそオブジェクト指向というやつ(多分えらい人には怒られる文脈)
コンピュータプログラムの設計や実装についての考え方の一つで、互いに密接に関連するデータと手続き(処理手順)をオブジェクト(object)と呼ばれる一つのまとまりとして定義し、様々なオブジェクトを組み合わせて関連性や相互作用を記述していくことによりシステム全体を構築していく手法。
参考 : https://e-words.jp/w/オブジェクト指向.html
Userクラスを用意しておけばmainの処理は以下のようになる。
code:main2.dart
void main() {
// いわゆるインスタンス化
final a = User(60, 170);
final bmi = a.calculateBMI();
final idealWeight = a.calculateIdealWeight();
final dailyEnergyNeeds = a.calculateIdealWeight();
print('AさんのBMI $bmi');
print('Aさんの標準体重 $idealWeight');
print('Aさんの1日に必要な適正エネルギー $dailyEnergyNeeds');
print('-------------------');
// いわゆるインスタンス化
final b = User(70, 160);
final bmi2 = b.calculateBMI();
final idealWeight2 = b.calculateIdealWeight();
final dailyEnergyNeeds2 = b.calculateIdealWeight();
print('BさんのBMI $bmi2');
print('Bさんの標準体重 $idealWeight2');
print('Bさんの1日に必要な適正エネルギー $dailyEnergyNeeds2');
}
体重と身長を記述する場所が一箇所で済むようになった!
↓
まとめ)
引数って(関数の)大事な構成要素だけど、ないほうがシンプルじゃない?
逆に途中から引数が増えたりすると大変だよね
code:main2.dart
void main() {
final weight = // 体重を求める処理・取り出す処理
final height = // 身長を求める処理・取り出す処理
final bmi = calculateBMI(weight, height);
}
Riverpodで話すとfamilyつけた瞬間、実装が面倒になりません??
引数の部分が何かの情報の塊であるなら、別のriverpod経由で取り出した方がいいのでは?
例)アプリにログインしているユーザー情報など。
※ 決して、引数を無くすことが正義だと言いたいわけではない。
引数を無くす
デメリット
依存関係が見えにくくなる。
密なソースコードになってしまう可能性がある。
今回の文脈においては、
引数を無くしながら、密なソースコードにならないようにしてくれるものがDI
という説明になる。