皆さん命名規則守ってますか?
分かりやすいコードを書くためには必要ですよね。
今回は命名規則の中でも、Interface
について考えてみましょう。
※タイトルでは言い切ってますが、結局自分たちが書きやすい方法が正解です。
一つ、規約について考えるきっかけにしてみてくださいな。
本題の前に、よく見るサンプルの書き方
多くのプログラミング言語で使用されるInterface
ですが、
皆さんどのように名前つけてますか?
I
とかInterface
をつける書き方
例えばHoge
というクラスがあったとして、このクラスにつけるInterface
を作るとすると、
public class Hoge implements IHoge {
public void doSomething() {
// 何かする
}
}
public interface IHoge {
void doSomething();
}
とか、
public class Home implements HogeInterface {
public void doSomething() {
// 何かする
}
}
public interface HogeInterface {
void doSomething();
}
とか、こんな感じですかね?
(サンプルはJava
で書きます)
Hoge
クラスにつけるインタフェースですから、
- 頭に
I
をつける - おしりに
Interface
をつける
のどちらかをして、インタフェースだと分かるようにしておきましょうと。
まぁこれはいいでしょう。特に文句ないですね。
I
とかInterface
をつける書き方その2
ではこれだとどうでしょう?
public class Dog implements DogInterface {
public void walk() {
// 歩く
}
public void run() {
// 走る
}
}
public interface DogInterface {
void walk();
void run();
}
あぁっ!? さっきと同じなのに、なんか気持ち悪い!
となりますよね?なりませんか?
では、こう書いたらどうでしょう?
public class Dog implements Animal {
public void walk() {
// 歩く
}
public void run() {
// 走る
}
}
// 同じ機能を持った猫も作れる!
public class Cat implements Animal {
public void walk() {
// 歩く
}
public void run() {
// 走る
}
}
// Interfaceの名前を、より適切にする
public interface Animal {
void walk();
void run();
}
Interface
の名前をAnimal
にしたことによって、
Cat
のクラスに継承しても違和感が無い状態になりました。
問題の書き方
ここまで納得いただけたでしょうか。
では、次に今回問題にしたい書き方。
public class Dog implements AnimalInterface {
public void walk() {
// 歩く
}
public void run() {
// 走る
}
}
public class Cat implements AnimalInterface {
public void walk() {
// 歩く
}
public void run() {
// 走る
}
}
// 末尾に Interface をつける
public interface AnimalInterface {
void walk();
void run();
}
一つ目と二つ目のハイブリッドみたいな形ですね。
この書き方はどうでしょうか。
特に問題なさそうですか?
ではこのAnimalInterface
を実際に呼び出してみましょう。
// メソッドだけ抜き出し
public void doSomething(){
AnimalInterface dog = new Dog();
dog.walk();
}
public interface Cage(){ // カゴ(檻)ですね
void add(AnimalInterface animal); // カゴに動物を追加
}
どちらの例にしても、ここで欲しいのは動物です。
それがInterface
であるかどうかは、呼び出し側からしてみれば「どうでもいい」情報です。
そうではなく、
// メソッドだけ抜き出し
public void doSomething(){
Animal dog = new Dog();
dog.walk();
}
public interface Cage(){
void add(Animal animal);
}
このほうが見通しが良い訳です。
それに(こっちの方が重要ですが)呼び出し側が、呼び出すものがInterface
かどうかなんて気にしなくてすみます。
ですから、Interface
名にI(名前)
とか、(名前)Interface
とするのは、
基本的に余り良くないだろう、と言う事です。
HogeInterface
の書き方は本来のInterface
の書き方ではない?
そもそも、なぜInterface
とかをつけるとかつけないとか、そんな話になったのでしょうか。
そうです。最初に挙げた、Hoge
クラスに対してInterface
をつける場合、
クラスとインタフェースを区別するためにHogeInterface
とします、というお話からです。
そもそも、Interface
は、ある事象に対して、それが実装するべき内容を定義するためのものですから、
ある一つのクラスの為だけにInterface
が作られるという事自体が稀な事なのかもしれません。
例えばDog
という実装を書く場合Interface
としてAnimal
を定義する事と、DogInterface
を定義する事は、明らかに別の事になります。
どちらも今回はDog
クラスの為に定義されているものの、
-
Animal
: 扱うべき存在の抽象概念についての定義 -
DogInterface
:Dog
クラスという具体的存在についての定義
であり、定義している内容に違いがあると言う事です。
Interface
の本来の役割から考えると、扱う存在の抽象概念を定義する使い方の方が、この場合、より適切でしょう。
よって、Hoge
という具体的なクラスが存在する前提で作られているHogeInterface
は本来の使い方から少しずれた使い方なのです。
I
とかInterface
を、つけてはいけないのか?
では、IHoge
とかHogeInterface
のような書き方はあり得ないのでしょうか?
いえ、これが必要になるパターンがありますね?
そうです。DI
です。
DI
する場合には、互いの依存を切り離すために、Interface
を介してやりとりする場合がほとんどです。
この時、注入されるべきは明らかにDog
である部分に対してAnimal
インタフェースを使ってしまうとCat
クラスを注入されてしまう可能性があります(Dogにしかないメソッドを実行させたい場合などは、そもそもコンパイルが通りませんね)。
よって、このような場合ではDogInterface
を介してやりとりさせることで、確実にDog
が入ってくることを保証できます。
まとめ
- 基本的に
Interface
を作る際にはI(名前)
とか(名前)Interface
の形にしない -
Interface
名は扱うべき抽象概念を表した名前をつける -
DI
など、確実にクラスと1:1で紐付いたInterface
が必要な場合は、この限りでない
ちなみに
色々書きましたが、Java
を使ってる方ならList
インタフェースとか思い出してもらったら分かりやすいですよね。
後半でInterface
とは何か?みたいな話に突っ込んでるので、異論等々あるかと思います。
その場合は心の中で(こいつアホだな)と思うだけでなく、出来ればコメントで教えて下さい。