質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Q&A

解決済

3回答

957閲覧

Arrayを継承したサブクラスについて

sachatete

総合スコア18

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

0グッド

0クリップ

投稿2018/11/22 07:04

前提・実現したいこと

独自に作成したクラスがArrayを継承した時に、意図した結果を返すことができません。
PartsクラスがArrayを継承していない場合はBicycleクラスのインスタンスは

Ruby

1#<Bicycle:0x00007fbf3bad3020 @size="L", @parts=#<Parts:0x00007fbf3bad33e0 @parts=[#<Part:0x00007fbf3bad3778 @name="chain", @description="10-speed", @needs_spare=true>, #<Part:0x00007fbf3bad36d8 @name="tire_size", @description="23", @needs_spare=true>, #<Part:0x00007fbf3bad3638 @name="tape_color", @description="red", @needs_spare=true>]>>

上記のように、@partsにPartsクラスのインスタンスの@partsを持つことができるのですが、Arrayを継承すると

Ruby

1#<Bicycle:object_id @size="L", @parts=[]>

のように@partsが空の配列になってしまいます。プリントデバッグをしたところ、

Ruby

1class Parts < Array 2 attr_reader :parts 3 4 def initialize(parts) 5 @parts = parts 6 p parts 7 end 8〜〜〜〜 9end 10#=> [#<Part:0x00007fbf3bad3778 @name="chain", @description="10-speed", @needs_spare=true>, #<Part:0x00007fbf3bad36d8 @name="tire_size", @description="23", @needs_spare=true>, #<Part:0x00007fbf3bad3638 @name="tape_color", @description="red", @needs_spare=true>]

Partsの@partsには、配列に入ったPartクラスのインスタンスがきちんと入っていました。
しかし、Parts.newの戻り値は

Ruby

1Parts.new([chain, mountain_tire, front_shock, rear_shock]) 2#=> []

となってしまいます。

なぜこのような動きになるのでしょうか?
ご回答よろしくお願い致します。

該当のソースコード

Ruby

1class Bicycle 2 attr_reader :size, :parts 3 4 def initialize(args={}) 5 @size = args[:size] 6 @parts = args[:parts] 7 end 8 9 def spares 10 parts.spares 11 end 12end 13 14class Parts < Array 15 attr_reader :parts 16 17 def initialize(parts) 18 @parts = parts 19 p parts 20 end 21 22 def spares 23 parts.select{|part| part.needs_spare} 24 end 25 26 def size 27 parts.size 28 end 29end 30 31class Part 32 attr_reader :name, :description, :needs_spare 33 34 def initialize(args) 35 @name = args[:name] 36 @description = args[:description] 37 @needs_spare = args.fetch(:needs_spare, true) 38 end 39end 40 41 # ------------------------------------------------------------------------------------------ 42 43chain = Part.new(name: 'chain', description: '10-speed') 44road_tire = Part.new(name: 'tire_size', description: '23') 45tape = Part.new(name: 'tape_color', description: 'red') 46mountain_tire = Part.new(name: 'tire_size', description: '2.1') 47rear_shock = Part.new(name: 'rear_shock', description: 'Fox') 48front_shock = Part.new( 49 name: 'front_shock', 50 description: 'Manitou', 51 needs_spare: false 52) 53 54road_bike = Bicycle.new( 55 size: 'L', 56 parts: Parts.new([chain, road_tire, tape]) 57) 58#=> #<Bicycle:object_id @size="L", @parts=[]> 59 60Parts.new([chain, mountain_tire, front_shock, rear_shock]) 61#=> []

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

REPLの仕様です。

とりあえずirbでは

rb

1class Parts < Array 2 attr_reader :parts 3 4 def initialize(parts) 5 @parts = parts 6 end 7 8 def inspect 9 @parts.inspect 10 end 11 12 def spares 13 parts.select{|part| part.needs_spare} 14 end 15 16 def size 17 parts.size 18 end 19end

inspectメソッドを追加することで
Parts.new([chain, mountain_tire, front_shock, rear_shock])
の結果が

=> [#<Part:0x0000000002dd3a90 @name="chain", @description="10-speed", @needs_spa re=true>, #<Part:0x0000000002baf1d8 @name="tire_size", @description="2.1", @need s_spare=true>, #<Part:0x0000000002d12610 @name="front_shock", @description="Mani tou", @needs_spare=false>, #<Part:0x0000000002cf1f28 @name="rear_shock", @descri ption="Fox", @needs_spare=true>]

になりました。


細かい話をするとirbの場合は=>で表示される式の値はinspectで文字列化したものになるので
Arrayのinspectメソッドを使ったらselfの値が表示されてしまうわけです。

なお、selfを書き換えたいのならreplaceを使うなりinitializeメソッドでsuperを使うなりしてください

投稿2018/11/22 08:42

asm

総合スコア15147

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sachatete

2018/11/29 05:09

ありがとうございます!
guest

0

上記のスクリプトをそのまま実行してみましたが、Parts.new の方は[] ではなくちゃんと入っていました。(159709.rbという名前でスクリプトを保存しました)

$ ruby 159709.rb : : [#<Part:0x00007f9c8784a208 @name="chain", @description="10-speed", @needs_spare=true>, #<Part:0x00007f9c8784a168 @name="tire_size", @description="23", @needs_spare=true>, #<Part:0x00007f9c8784a0c8 @name="tape_color", @description="red", @needs_spare=true>] [#<Part:0x00007f9c8784a208 @name="chain", @description="10-speed", @needs_spare=true>, #<Part:0x00007f9c8784a028 @name="tire_size", @description="2.1", @needs_spare=true>, #<Part:0x00007f9c87849ee8 @name="front_shock", @description="Manitou", @needs_spare=false>, #<Part:0x00007f9c87849f88 @name="rear_shock", @description="Fox", @needs_spare=true>]

投稿2018/11/22 07:12

oh_rusty_nail

総合スコア319

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sachatete

2018/11/22 07:53

ありがとうございます。 Parts::newのインスタンス変数には値が設定されるのですが、Pasts::newの戻り値が[]になってしまいます。 Bicycleの@partsはPasts::newの戻り値が代入されるので、Bicyle#partsが[]になってしまいます。
guest

0

ベストアンサー

Arrayとしての初期化をするためには、superを呼ぶ必要があります。

…というより、なんのために「Arrayを継承した自前のクラス」を作らなければならなかったのでしょうか。使い方によってはコンポジションのほうが適当かもしれません。

投稿2018/11/22 07:10

maisumakun

総合スコア145183

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sachatete

2018/11/22 07:15

ありがとうございます。 superを呼ぶ必要があるのですね。 このコードはコンポジションの使い方の説明をしている教材で、コンポジションの説明に至るまでにArrayを使ってやってみるというものでした。説明不足で申し訳ないです。 superを使った場合はどのようなコードになるか教えていただけないでしょうか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問