0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

値の定義の順番

Posted at

トップレベルのクラス、Clockモジュールのクラスなのか判断できない

irb(main):001* class Second
irb(main):002*   def initialize(player, uniform_number)
irb(main):003*     @player = player
irb(main):004*     @uniform_number = uniform_number
irb(main):005*   end
irb(main):006> end
=> :initialize
irb(main):007* module Clock
irb(main):008*   class Second
irb(main):009*     def initialize(digits)
irb(main):010*       @digits = digits
irb(main):011*     end
irb(main):012*   end
irb(main):013> end
=> :initialize
irb(main):014* module Clock
irb(main):015*   class Second
irb(main):016*     def initialize(digits)
irb(main):017*       @digits = digits
irb(main):018*       @baseball_second = Second.new("Clock", 10)
irb(main):019*     end
irb(main):020*   end
irb(main):021> end
=> :initialize
irb(main):022> Clock::Second.new(13)
(irb):16:in `initialize': wrong number of arguments (given 2, expected 1) (ArgumentError)

::をつけることでトップレベルのクラスを表現し区別することができる

irb(main):001* class Second
irb(main):002*   def initialize(player, uniform_number)
irb(main):003*     @player = player
irb(main):004*     @uniform_number = uniform_number
irb(main):005*   end
irb(main):006> end
=> :initialize
irb(main):007* module Clock
irb(main):008*   class Second
irb(main):009*     def initialize(digits)
irb(main):010*       @digits = digits
irb(main):011*       @baseball_second = ::Second.new("Clock", 10)
irb(main):012*     end
irb(main):013*   end
irb(main):014> end
=> :initialize

irb(main):017> clock_second = Second.new("Alice", 12)
=> #<Second:0x000000010c5f5ca0 @player="Alice", @uniform_number=12>
irb(main):018> clock_second = Clock::Second.new(13)
=> #<Clock::Second:0x000000010c6bd160 @baseball_second=#<Second:0x000000010c6bd0c0 @player="Clock", @uniform_number=10>, @digits=13>

定数参照の優先順位

親クラスとネストの外側のクラスで同名の定数が定義されているとネストの外側の定数の方を先に参照します。つまり、定数参照時の定数の探索順序は、最初にネスト関係を外側に向かって探索し、次に継承関係を上位に向かって探索します。

class Foo
  CONST = 'Foo'
end

class Bar
  CONST = 'Bar'

  class Baz < Foo
    p CONST             # => "Bar"      外側の定数
    # この場合、親クラスの定数は明示的に指定しなければ見えない
    p Foo::CONST        # => "Foo"
  end
end
class Foo
  CONST = 'Foo'
end

class Bar
  CONST = 'Bar'

  class Baz < Foo
    p CONST             # => "Bar"      外側の定数
    # この場合、親クラスの定数は明示的に指定しなければ見えない
    p Foo::CONST        # => "Foo"
  end
end

トップレベルの定数定義はネストの外側とはみなされません。したがってトップレベルの定数は、継承関係を探索した結果で参照されるので優先順位は低いと言えます。

class Foo
  CONST = 'Foo'
end

CONST = 'Object'

class Bar < Foo
  p CONST               # => "Foo"
end

# 以下のように明示的にネストしていれば規則通り Object の定数
# (ネストの外側)が先に探索される
class Object
  class Bar < Foo
    p CONST             # => "Object"
  end
end
class Foo
  CONST = 'Foo'
end

CONST = 'Object'

class Bar < Foo
  p CONST               # => "Foo"
end

# 以下のように明示的にネストしていれば規則通り Object の定数
# (ネストの外側)が先に探索される
class Object
  class Bar < Foo
    p CONST             # => "Object"
  end
end

上位のクラス(クラスの継承関係上、およびネストの関係上の上位クラス)の定数と同名の定数(下の例で CONST) に代入を行うと、上位の定数への代入ではなく、そのクラスの定数の定義になります。

class Foo
  CONST = 'Foo'
end

class Bar < Foo
  p CONST               # => "Foo"
  CONST = 'Bar'         # Bar の定数 CONST を*定義*
  p CONST               # => "Bar"  (Foo::CONST は隠蔽される)
  p Foo::CONST          # => "Foo"  (:: 演算子で明示すれば見える)
end

感想

ネストされた外側の定数定義の方が優先的
定義するときはどこの何の変数、定数に対してを指定する

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?