他の言語のように継承や実装などを利用しながら、クラスのメンバのアクセス可能なスコープを考えてみる
今北産業
- Dartのprotectedの実現例
- DartのFactoryパターン実装例
- Dartの基本的な継承、実装
protectedなメンバ変数の実現
Dartにはprotectedは存在しないため、スコープをサブクラスに限定したメンバへのアクセスの実現には少し工夫が必要です
実装例 抽象クラスで宣言、実装を行う
super classで継承するクラス共通の処理を行いつつ、サブクラスでは独自の実装を行うような設計を行う時にはこのような手段が取れます。
abstract class UserRepository {
User get _user;
int userId() {
return _user.id;
}
String name() {
return _user.name;
}
}
class HotelGuestUserRepository extends UserRepository {
@override
final User _user;
String guestName() {
return 'hotel guset ' + _user.name;
}
HotelGuestUserRepository({required user}): _user = user;
}
少し複雑なポリモーフィズムの実現 Factoryパターン
サブクラスもいくつかの系統に分かれていて、系統ごとに同じinterfaceを定義できる場合、Factoryパターンなどでカプセル化とポリモーフィズムを利用した設計をしたくなるかと思います。
実装例
abstract class UserRepository {
User get _user; // ①
int userId() {
return _user.id;
}
String name() {
return _user.name;
}
}
abstract class GuestUserRepository implements UserRepository { // ②
String guestName();
}
class HotelGuestUserRepository extends UserRepository implements GuestUserRepository { // ③
@override
final User _user;
@override
String guestName() {
return 'hotel guset ' + _user.name;
}
HotelGuestUserRepository({required user}): _user = user;
}
class GuestUserRepositoryFactory {
static GuestUserRepository create({required User user}) {
return HotelGuestUserRepository(user: user);
}
}
void main() {
var user = User(1, 'John Doe');
GuestUserRepository guestRepo = GuestUserRepositoryFactory.create(user: user);
print('Guest Name: ${guestRepo.guestName()}'); // ④ 出力: Guest Name: hotel guest John Doe
print('User ID: ${guestRepo.userId()}'); // ⑤ 出力: User ID: 1
print('Name: ${guestRepo.name()}'); // 出力: Name: John Doe
}
解説
① Userをprotectedのアクセススコープにしたいため、super classではprivateなgetterとして定義する
② Factoryの戻り値型として利用するため、UserRepositoryのinterfaceを実装する
③ super classを継承し、interface定義であるGuestUserRepositoryを実装する
④ ③の実装でGuestUserRepositoryのinterfaceを実装しているのでアクセス可能
⑤ ②の実装でUserRepositoryのinterfaceを実装しているのでアクセス可能
Dartの実装
DartのInterfaceは抽象クラスでも具象クラスを定義しても生成される
// 具象クラス
class User {
String name;
User(this.name);
}
// 継承に見えるが実装
class GuestUser implements User {
@override
String name; // 具象クラスのnameメンバ変数を実装
GuestUser(this.name);
}
// 抽象クラス
abstract class User {
int get id;
String name;
}
// 継承ではなく実装
class GuestUser implements User {
@override
int id; // 抽象クラスのid getterをproperty実装
@override
String name; // 抽象クラスのnameプロパティを実装
GuestUser(this.id, this.name);
}
Dartの継承
class User {
String name;
User(this.name);
}
class GuestUser extends User {
GuestUser(String name) : super(name);
}
abstract class User {
String name;
int get id;
User(this.name);
}
// 継承
class GuestUser extends User {
GuestUser(this.id, String name) : super(name);
@override
int id; // idゲッターを実装
}