Ruby
PHP

PHPとRubyを比較してカプセル化ついて理解する_100DaysOfCodeチャレンジ23/24日目(Day_23/24:#100DaysOfCode)

はじめに

この記事はTwitterで人気のハッシュタグ#100DaysOfCodeをつけて、
100日間プログラミング学習を続けるチャレンジに挑戦した23日目の記録です。

動作環境

  • PHP 7.1.16 (cli)
  • Ruby 2.4.1p111 (2017-03-22 revision 58053)

本日学んだこと

  • カプセル化について
  • getterについて
  • publicとprivate

カプセル化とは?

内部のデータをいじることはできないというのは、例えばiPhoneは液晶部分は操作できますが、本体の中身は基本的に特別な器具がないと開けることはできないですよね。

iPhone内部にあるパーツなどはユーザーがいじれないように隠すことで、予期せぬ故障を未然に防いでいることになります。

この隠すことを、プログラミングの専門用語でカプセル化と言います。

プログラミングにおいて、カプセル化を意識することは特に重要で、読みやすさだけでなく、堅牢性の高いコードを保つことができます。

publicとprivate

カプセル化には、publicとprivateがあります。publicに指定したメソッドなどは外部からアクセス可能ですが、privateを指定すると、呼び出す際にエラーとなります。

publicの場合

<?php 
  class Animal {
    public $kind;
    public function __construct($kind) {
      $this->kind = $kind;
    }
  }
  // ここから下は外部(クラスのスコープ外)
  $penguin = new Animal('キングペンギン');
  echo $penguin->kind; //=> キングペンギンが出力される
?>
class Animal
  public #=>何も指定しなければrubyはデフォルトでpublicになる
  attr_accessor :kind  # attr_accessorでgetterとsetterをまとめて定義
  def initialize(kind)
      puts kind
  end
end

# ここから下は外部(クラスのスコープ外)
penguin = Animal.new('キングペンギン')
puts penguin.kind #=>キングペンギンが出力される

privateの場合

<?php 
  class Animal {
   private $kind;
   public function __construct($kind) {
    $this->name = $kind;
   }
  }
  // ここから下は外部(クラスのスコープ外)
  $penguin = new Animal('キングペンギン');
  echo $penguin->kind; //=> エラー発生
?>
class Animal
  private
  attr_accessor :kind

  def initialize(kind)
      @kind = kind
  end
end

# ここから下は外部(クラスのスコープ外)
penguin = Animal.new('キングペンギン')
penguin.kind #=>エラー発生

ゲッターについて

privateに設定したことで、外部(クラスの外)からプロパティやインスタンス変数にアクセスすることができなくなりました。

アクセスできない代わりに、その値を返すだけ(=取得する) のメソッドをクラス内で定義するのが一般的です。

その値を返すだけのメソッドをゲッターと呼びます。

なお、Rubyではゲッターとセッターをまとめてアクセサと呼んでいます。

<?php 
  class Animal {
   private $kind;
   public function __construct($kind) {
    $this->kind = $kind;
   }
   public function getKind() {
    return $this->kind;
   }  
  }
  // ここから下は外部(クラスのスコープ外)
  $penguin = new Animal('キングペンギン');
  echo $penguin->getKind(); //=> キングペンギン
?>
class Animal

  def initialize(kind)
      @kind = kind
  end

  def kind
    @kind
  end
end

# ここから下は外部(クラスのスコープ外)
penguin = Animal.new('キングペンギン')
p penguin.kind #=>キングペンギン

セッターとは?

privateに設定したことで、外部(クラスの外)からプロパティやインスタンス変数の値を変更することができなくなりました。

このままでは一度設定した値をずっと使うことになってしまうので、代わりにプロパティやインスタンス変数の値を変更するためのメソッドを定義します。

この値が変更できるように定義したメソッドがセッターになります。

<?php 
  class Animal {
   private $kind;
   private $count;
   public function __construct($kind) {
    $this->kind = $kind;
   }
   public function setCount($count) {
    $this->count = $count;
   }
   public function getCount() {
    return $this->count;
   }  
  }
  // ここから下は外部(クラスのスコープ外)
  $penguin = new Animal('キングペンギン');
  $penguin->setCount(3);
  echo $penguin->getCount(); //=> 3
?>
class Animal

  def initialize(kind)
      @kind = kind
  end

  # ゲッター
  def kind
    @kind
  end

  # セッター
  def kind=(value)
    @kind = value
  end
end

# ここから下は外部(クラスのスコープ外)
penguin = Animal.new('キングペンギン')
penguin.kind="イワトビペンギン" #=>代入しているように見えるけど、`kind=`メソッドの呼び出している。
p penguin.kind#=>セッターによって値が書き換わったので、キングペンギンではなく、イワトビペンギンが出力される。