学び直し Rubyがミニツク Part8

今日の教科書
[継承](http://www.minituku.net/courses/566428009/contents/43567039.html)

#継承
すでに定義されているクラスから機能を引き継いで新しいクラスを作ること。
作るときにスーパークラス(親クラス)となるクラスを指定すると継承できる。

```
class サブクラス　< スーパークラス
本体
end 
```

継承で新しく作られたクラスをサブクラス、継承元のクラスをスーパークラスと呼ぶ。
スーパーにできるのは一つだけ！

```
class Foo
  def foo
    puts("foo")
  end
end
 
class Bar < Foo
  def bar
    puts("bar")
  end
end
 
bar = Bar.new
bar.foo  #=> foo
bar.bar  #=> bar
```

継承によってサブクラスができること
 - スーパーの機能を全て使用でき、新しい機能を追加
 - スーパーの機能を上書きして、同じ名前のメソッドを作れる
 - スーパーの機能を呼び出して、その機能に処理を追加して拡張

#is_a?メソッド

 > サブクラスとスーパークラスの関係を「is-aの関係」といいます。is_a?メソッドを使うことによって、レシーバに指定したオブジェクトがクラスに属しているのかを判定できます。is_a?メソッドは継承関係をさかのぼって、レシーバがクラスに属しているかを調べることができます。

```
class Foo
end
class Bar < Foo
end
class Baz < Bar
end
baz = Baz.new
baz.is_a?(Baz)
baz.is_a?(Bar)
baz.is_a?(Foo)
```

#オーバーライド
継承でスーパークラスの機能をサブに提供する。

```
class Foo
  def foo
    puts("foo")
  end
end
class Bar < Foo
  def foo
    puts("override")
  end
end
bar = Bar.new
bar.foo  #=> override
```

同じ名前のメソッドをサブで定義する。
サブで同じ名前のメソッドを定義し直すことをオーバーライドという。
これでスーパーのメソッドをサブで書き換えることが可能。
オーバーライドのメソッドをサブで呼び出すこともできる。

```
class Foo
  def foo
    puts("foo")
  end
end
class Bar < Foo
  def foo
    super
    puts("foo")
    super
  end
end
bar = Bar.new
bar.foo
```

`super`：オーバーライドされたメソッドの元の振る舞いを呼び出す。
サブでオーバーライドしたメソッドは、コードのコピーを行わず機能を拡張できる。

```
class Foo
  def foo(args=5)
    p args * 2 
  end
end
class Bar < Foo
  def foo(args=2)
    super(10)
    super
    super()
  end
end
bar = Bar.new
bar.foo
  #=> 20
  #=> 4
  #=> 10
```

superに引数を与えることもできる。引数を指定しない場合、デフォルト値が渡される。
引数なしでオーバーライドのメソッドを呼ぶにはsuper()と書く。
()なしだと、サブクラスのオーバーライドしたメソッドの引数のデフォルト値が渡される。

##superclass
あるクラスのスーパーを知りたい場合、superclassメソッドを使う。

```
class Foo
end
class Bar < Foo
end
p Bar.superclass  #=> Foo
```

#アクセス制限
https://www.javadrive.jp/ruby/private/index1.html

 > Rubyにおける可視性とは、主にメソッドの可視性に関する話です。言い換えると、Rubyの可視性とはメソッドをどこから呼び出せるかについて設定をおこなう機能です。
クラスの中でメソッドを定義すると、インスタンスメソッドとして呼び出すことができます。ただし、クラスの内部だけでしか使わない(外部に公開する予定の無い）メソッドも同じように呼び出せては困ります。そのような時に以下のメソッドを使うことによって、メソッドの可視性を変えることができます。
public
private
protected
これらを指定するには、以下のようなやり方があります。
引数にメソッド名をシンボルで指定して、メソッドの可視性を変える
引数を与えずにメソッドを呼び出して、可視性のデフォルトの設定を変える
publicに設定されたメソッドは、パブリックメソッドと呼びます。privateに設定されているメソッドのことを、プライベートメソッドと呼び、protectedに設定されているメソッドのことを、プロテクテッドメソッドと呼びます。

```
def foo
  puts("foo")
end
 
public :foo
private :foo
 
class Foo
  public
  def foo
    puts("foo")
  end
  private
  def bar
    puts("bar")
  end
  protected
  def baz
    puts("baz")
  end
end
```

 > クラスの中で定義したメソッドは（initializeメソッドを除いて）、何も設定をしていない状態だとpublicになります。publicはメソッドを呼び出すのにまったく制限がないことを表します。そのため、どこからでもpublicに設定されているメソッドは呼び出せます。privateはメソッドを定義したクラスの中か、そのクラスを継承したサブクラスのメソッドの中で呼び出せます。つまり、プライベートメソッドはオブジェクトの外側から使えません。

```
class Foo
  private
  def foo
    puts("foo")
  end
end
class Bar < Foo
  def call_foo
    foo
  end
end
bar = Bar.new
bar.call_foo
```

 > protectedはprivateと似ていますが、プロテクテッドメソッドは、クラス（またはそのクラスのサブクラス）に属してる各オブジェクトから呼び出せます。レシーバを指定した形やレシーバを指定しない形（つまり、関数的なメソッド）のどちらでも呼び出せます。

```
class Foo
  protected
  def foo
    puts("Protected Method foo")
  end
  private 
    def bar
      puts("Private Method bar")
    end
  public 
  def useFoo(o)
    o.foo
  end
  def useBar(o)
    o.bar
  end
end
 
 
fooReciever = Foo.new
fooSender = Foo.new
 
fooSender.useFoo(fooReciever) # "Protected Method foo"が表示される
fooSender.useBar(fooReciever) # NoMethodErrorが発生します
```