💭

インターフェースを継承するって言ってない?

2024/08/12に公開2

今回は、継承と実装の言葉の違いについてやっていきたいと思います。インターフェースの継承という表現をしていますか? していないですか? というようなお話なのですけど、例えば次のコードを見てください。

public abstract class EntityBase
{
  public abstract int GetId();
  public void ToRow()
  {
  }
}

public class ProductEntity : EntityBase
{
  public override int GetId()
  {
    return 1;
  }
}

EntityBaseっていう抽象クラス抽象クラスがあって、ProductEntityには「:」(コロン)でつないでEntityBaseという風に書いています。これは「継承している」っていうことですね。EntityBaseを継承して、abstractで抽象メソッドになっているGetIdをoverrideでサブクラスであるProductEntityが独自に実装しているという関係性ですね。

これを言葉にすると、「ProductEntityはEntityBaseを継承しています」という表現になります。

続いて次のコードを見てください。

public interface IMember
{
  int GetPoint();
}

public class GoldMember : IMember
{
  public int GetPoint()
  {
    return 20;
  }
}

IMemberというインターフェースがあって、GoldMemberという普通のクラスがあります。GoldMemberも「:」(コロン)でつないでIMemberインターフェースを書いているのですが、今回は「これを何と表現していますか?」 というお話です。

「継承している」のではなく「実装している」

「IMemberを継承している」、「GoldMemberはIMemberを継承している」という表現をしている方がたまにいると思いますが、この場合は継承ではなくて実装です。

インターフェースには基本的には定義だけがあって、それの実装を普通のクラスで行なう訳なのですが、IMemberの定義に対してGoldMemberというのは、その実装を書いているわけです。ですので、この場合GoldMemberはIMemberの実装をしているということになります。

誤解する理由

C#の場合は「実装」でも「継承」でもキーワードを「コロン」を使って書くので、どうしても、どちらとも継承だと思ってしまいがちなのですが、Javaであればインターフェースの実装であればimplements、クラスの継承の場合はextendsを使うので、その違いをはっきりと認識できます。今回の例のようにIMemberインターフェースの実装クラスを記述する場合は、javaでは次のようになります。

public class GoldMember implements IMember
{
  public int GetPoint()
  {
    return 20;
  }
}

implements は「実装」という意味です。IMemberの実装がGoldMemberということになります。

継承の場合は、javaではextendsになるので、次のようになります。

public class ProductEntity extends EntityBase
{
  public int GetId()
  {
    return 1;
  }
}

extendsは「広げる」とか「拡張する」という意味になります。ですのでEntityBaseを継承します、EntityBaseを拡張しますといったイメージになる訳です。

このようにjavaではインターフェースの実装クラスを書く場合はimplements、クラスを継承する場合はextendsを使うので、実装と継承のイメージが付きやすいと思いますが、C#ではどちらもコロンで記載するため、両者の違いが認識できていないプログラマーもいるかもしれません。

この誤解がもたらす影響

「この違いが判らなくても問題はないのでは?」と思うかもしれませんが、例えばオブジェクト指向の考え方の中で「継承というのはあまり乱用しないほうがいい」という考え方があります。継承はベースクラスの機能をすべて引き継ぐため、ベースクラスとサブクラスを読んで初めて機能を理解することができるため、「継承」を乱用すると、わかりづらいコードになる傾向になります。例えばこの教えを学ぶ上で、「継承」と「実装」の違いを理解できていなければ、「インターフェースの実装クラスもあまり作らないほうがいいのか?」という間違った認識をしてしまうことになります。ですので、書き方はコロンで同じですが、違いを理解しておくのは重要なことだとおもいます。

本当の「インターフェースを継承する」ということ

ちなみに「インターフェースを継承する」というのは次のようなコードになります。

public interface IMemberPro : IMember
{
  public int GetProPoint();
}

IMemberインターフェースを拡張して、別のインターフェースを作成する場合は、「IMemberインターフェースを継承して、IMemberProインターフェースを作成する」という表現になります。

Discussion