Ruby Angleクラス作成方法とは?

このQ&Aのポイント
  • Rubyにてゲームプログラミングをしている方へ、Angleクラスで数値を制限する方法を紹介します。
  • Angleクラスの作成方法は記号や配列を使用しないシンプルな方法です。
  • クラス参照で値を取得する方法も紹介しています。
回答を見る
  • ベストアンサー

Ruby Angleクラス作成方法について

Rubyにてゲームプログラミングをしているのですが、 Angleとして使用する数値を (0..360) の範囲内に常に収める為、Angleクラスで管理しようと思っています。 そこで作成方法の質問なのですが、記号などによる適切な作成方法が分かりません。 適切な記述を教えて頂けたら幸いです。 angle = Angle[30]     # Vectorを参考にしたのですが、配列では無い為、微妙な記述・・・ angle = Angle.new(30)  # かと言って、普通に作成するのもどうかと・・・ また、attr_readerで参照するのも微妙な記述だと思います。 angle = Angle.new(30) angle.angle  # => 30 できればクラス参照で値を取得したいのですが、方法が分かりません。 angle = Angle.new(30) angle  # => 30 ご教授の程、お願い致します。

  • Ruby
  • 回答数4
  • ありがとう数1

質問者が選んだベストアンサー

  • ベストアンサー
  • notnot
  • ベストアンサー率47% (4848/10262)
回答No.4

No3です。 >Numeric並に手軽に呼び出せた方が良いと思ったからです。 それは無理です。せいぜい、組み込みクラスのRationalのように、 def Angle(x) Angle.new(x) end と、クラス名と同名の関数(Kernelのメソッド)を定義するくらいですね。 >クラスのみ参照で、戻り値(Numeric)を取得したいです。 >angle  # => 30(Numeric)のオブジェクト いやだから、それはわかっていて、それを文字通りにするのは無理なので、それに対しての回答が、 >数値演算関係がすべて定義されているなら、あとは to_int to_i to_f to_s inspect 等を適切に定義すれば良いです。 です。 p angle で 30 を表示するためには、inspect を定義すれば良いし、puts angle なら to_s を定義すれば良いと言うことです。 ただ、 >30 + Angle.new(30) >Numeric側の演算子定義を直すのも手なのですが、 ということは、上記回答の前提の、「数値演算関係がすべて定義されているなら」もまだと言うことですね。 30 + Angle.new(30) の結果は、Angleオブジェクトじゃ無くてNumericオブジェクトということでいいですか?であれば、Numericクラスを修正するので無くAngle#coerceを定義してください。 class Angle def coerce(other) [other, @angle] end end ただ、そもそも 30 + Angle.new(30) などという計算をするのはおかしくないですか? Angle.new(30) + Angle.new(30) とするべきでは?

tsanndayo
質問者

お礼

引き続き何度もご回答して頂きありがとうございます。 Kernelのメソッドを定義する方法は、正に思っていたような記述です!! 作成はそれでやってみます。 >いやだから、それはわかっていて、それを文字通りにするのは無理なので やはりクラス参照のみでは、Numericオブジェクトは取得できませんでしたか・・・。 上記の方法でやってみます。 >ということは、上記回答の前提の、「数値演算関係がすべて定義されているなら」もまだと言うことですね。 これについては、Angleクラス内の演算子関係を全て定義していることだと思っていました。 coerceメソッド、ヘルプで見ました。かなり使えるメソッドだと思います。 (ヘルプくらい、もっと前にしっかりと読みこんでおくべきでした・・・) 是非、これを使いたいと思います。 >Angle.new(30) + Angle.new(30) とするべきでは? もちろんそのつもりです。ただ、そういう使い方をする可能性も視野に入れておきたかったのです。 お蔭様で、思っていたような処理を組むことが出来そうです。 とても参考になりました。ありがとうございます。 これで、また一歩先に進めそうです。

その他の回答 (3)

  • notnot
  • ベストアンサー率47% (4848/10262)
回答No.3

>newを使わずに作成した方がAngleらしい記述だと思うのですが、 そんなことはないです。なぜそう思ったのですか?なんとなくですか? >また、参照もメソッドを呼び出さず、クラスのインスタンスを参照するやり方を教えて頂きたいのです。 数値演算関係がすべて定義されているなら、あとは to_int to_i to_f to_s inspect 等を適切に定義すれば良いです。

tsanndayo
質問者

補足

ご回答ありがとうございます。 newが、Angleらしくない記述だと思った訳は、Angleは頻繁に使う物であり、 Numeric並に手軽に呼び出せた方が良いと思ったからです。 また、Vector[]は配列らしさを取り込んだ上手い記述だと思ったので、そのような分かり易い記述にしようと思いました。 それと、お聞きしたいことが上手く伝わらなかったようなので、質問をもう少し補足したいと思います。 またまた分かりづらい質問になってしまい申し訳ありません。 class Angle  attr_reader :angle  def initialize(angle)   @angle = angle  end end angle = Angle.new(30) angle.angle  # => 30(Numeric)のオブジェクト 上記のように定義するとそうなるのですが、下記のようにしたいのです。 クラスのみ参照で、戻り値(Numeric)を取得したいです。 angle  # => 30(Numeric)のオブジェクト しかし、やり方が分かりません。 google先生や、リファレンスもある程度見たのですが、見つかりませんでした・・・。 試行錯誤としては、下記のようにメソッドを組んでみたのですが、当然呼び出せません。 def self  @angle end このやり方で呼び出したい理由としては、下記のような計算があった時に、Numericとして渡したいからです。 30 + Angle.new(30) Numeric側の演算子定義を直すのも手なのですが、AngleはNumeric以外の様々な場所で使われているので、 そのまま使えるのが効率的だと思っています。 演算子を直すことになると、Numeric以下の様々なクラスを修正する必要も出てきます・・・。 例としては、下記のようなケースも考えられます。 angle = Angle.new(30) sprite = Sprite.new sprite.angle = angle.angle  # 現状、このように呼び出すしかない。 # sprite.angle = angle     # 本当はこのように呼び出したい。 尚、Spriteクラスはブラックボックス化されており、ソースを弄る事ができません・・・。 (つまり、angleに渡す値はNumericでないといけないということです。) angle.angleと、二重にangleを記述しないと呼び出せないのでは、優れた記述とは言えないと思います。 to_int、to_i、to_f、to_sは、今のところ使うつもりはないので定義していません。 inspectについてなのですが、思っていたことに非常に近いことが出来ました。ご教授ありがとうございます。 しかし、p で参照した値が計算の際にそのまま渡されると思っていたので、やはり思っていたようにはできませんでした・・・。 何度も補足してしまい、申し訳ありません・・・。 ご回答の程、宜しくお願い致します。

  • ki073
  • ベストアンサー率77% (491/634)
回答No.2

補足欄の意味が分かりにくいのですが、 angle = Angle[30] を使えるようにしたいのでしたら def self.[](ang) @angle=ang end で可能ですが、多分聞きたいことと違うような気がします。 p angle で角度が表示されるようにするには、 def inspect @angle.to_s end で可能なのですが、あくまでも表示だけを変更しているだけです。

tsanndayo
質問者

補足

引き続きご回答ありがとうございます。 回答内容がこちらから閲覧できなかった為、返信が遅くなってしまいました。 分かりづらい補足で申し訳ありません。 詳しい補足は、回答NO3のnotnot様の補足に書いたのでそちらの閲覧をお願いいたします。 何度も補足をしてしまい申し訳ありません。 作成方法については、Angle[30]の変わりに、良い記述方法のアドバイスが欲しいのです。 Angle{30}とか、何か記号を使った良い記述を教えて頂きたいのです。 (できれば、Numeric並に楽に作成できるのが望ましいです。) また、inspectが表示だけしか変更できないということに、先程気がつきました。 angle = Angle.new(30) angle  # 30(Numeric)のオブジェクト 表示だけでなく、上記のように見なされるように変更したいです。 そのような方法は、不可能でしょうか・・・? ご回答お願い致します。

  • ki073
  • ベストアンサー率77% (491/634)
回答No.1

こんな感じでしょうか class Angle attr_accessor :angle def initialize(ang) @angle=ang end def to_s() @angle.to_s end def +(other) self.class.new(case other when Angle then @angle+other.angle else @angle+other end) end end p ang1=Angle.new(30) p ang1.angle ang1.angle=45 p ang1 puts ang1 #=>45 p ang1+12 puts ang1+12 #=>57 puts ang1+Angle.new(12) #=>57 ang1はNumeric classではありませんので、演算は定義してやる必要があります。 演算した結果がNumericで良いのなら、forwardableを使って委譲する手もあります。 参考 http://jp.rubyist.net/magazine/?0012-BundledLibraries

tsanndayo
質問者

補足

お早い回答ありがとうございます。 質問が分かりづらくて申し訳ありません。 演算子定義などは、Vectorクラスを参考に作成できるのですが、 作成の際の記述方法が分からなくて困っています。 newを使わずに作成した方がAngleらしい記述だと思うのですが、 配列ではないので、Angle[30]などのように作成するのもどうかと思い、適切な作成方法を知りたいのです。 また、参照もメソッドを呼び出さず、クラスのインスタンスを参照するやり方を教えて頂きたいのです。 angle = Angle[30] p angle   # => 30 (angle.angleと二重に書かなくても参照可能) ということでお願い致します。

関連するQ&A

  • Ruby1.9で、グローバル参照可能な(クラス間で参照可能)構造体の2

    Ruby1.9で、グローバル参照可能な(クラス間で参照可能)構造体の2次元配列の定義方法が分かりません。 色々と文献を読んでいますが、 ・構造体や配列をグローバル参照可能にする定義 ・2次元配列の定義の方法 について、見つけきれておりません。 どうか、ご教示の程お願いいたします。 投稿日時 - 2010-08-04 21:49:17

  • RubyのDateクラスのメソッドが見つからない

    先日よりRubyでのプログラミングを始めてみたのですが DateクラスのDate::MOTHNAMESを参照しようとしたところ undefined method `MOTHNAMES' for Date:Class (NoMethodError) と返ってきてしまいました。 ほかにもDate::exist?メソッドもためしてみましたが、同じ様なコメントが 返ってきました。 undefined method `exist?' for Date:Class (NoMethodError) なお、 Date.newなどはつかえています どういった問題でどのように解決すれば良いのか、ご教示願えればと思います。 バージョンは ruby 1.9.3p0 (2011-10-30 revision 33570) [x86_64-darwin11.2.0] で、Mac OSX Lionで動かしています。

  • Rubyでプログラミングを習っています。

    Rubyでプログラミングを習っています。 入力した内容を配列になおす方法をおしえてください。

    • ベストアンサー
    • Ruby
  • クラス内で作成したクラスへのアクセス方法。

    こんにちは、C++のプログラミングについて質問させて頂きます。 現在クラスを使って簡単なゲームを作ってみようと勉強中なのですが、クラスの扱いについて質問があります。 void Object::FireBall() {    //初期化の内容は読まなくても大丈夫です。 Action FireBall = Action(10,Ref_x() + cos(angle * PI / 180.0f)*3,Ref_y() + cos(angle * PI / 180.0f) *3 ,5,100,40,40,4,true,"Action/FireBall1.png",6,3,2,1.0,Ref_angle(),true,false); } といったように、Objectクラス内でActionクラスを作成したとします。 このとき、メイン関数内でFireBallの各メンバにはどうやってアクセスすれば良いのでしょうか? Objectクラスのオブジェクトの名前がPlayer[1]だとしたとき、 Player[1]->FireBall.Draw_Graph() のようにやるのかと思っていたのですが、上手くいかず、調べてもイマイチ解らず行き詰まっているのです(内部クラスとはまた別ですよね?)。 もし宜しければ、教えて頂けると助かります。

  • Ruby の 文法に困ってます。

    以下のようなソースの場合、to_sメソッドは何時呼ばれているのでしょうか。またどういう意味を成しているのでしょうか。 Ruby初心者のためご教授頂けないでしょうか。 よろしくお願いします。 class Vector   attr_accessor :x, :y   def initialize(x=0, y=0)     @x = x     @y = y   end   def length     Math::sqrt(@x ** 2 + @y ** 2)   end   def to_s      "(#{@x},#{@y})"   end   def <=> other     length <=> other.length   end end arr =[] arr << Vector.new(2,2) arr << Vector.new(3,2) arr << Vector.new arr.sort.each do |item|   puts item end 結果は以下になります。 (0,0) (2,2) (3,2)

    • ベストアンサー
    • Ruby
  • ラッパークラスのオブジェクト作成について教えてください。

    ラッパークラスのオブジェクト作成について教えてください。 ラッパークラスのオブジェクト作成には ・new演算子を使ってインスタンス化する方法 ・ラッパークラスのstaticメソッドを呼び出す方法 の2つの方法があると書籍に書いてありました。(SJC-Pのテキストです) では Integer i = 1000; のような記述はどうでしょうか? Integerはintのラッパークラスと思うのですが、iはインスタンスじゃないという事でしょうか?

    • ベストアンサー
    • Java
  • VC++6.0で作成したクラスをVB6.0で使うには?

    初めて投稿します。 プログラミング初心者の為、初歩的な質問になるかもしれませんがご容赦下さい。普段、主にVisual Basic6.0(以下VB6.0)でプログラミングを行なっています。 VB6.0には演算子のオーバーロードする機能がない(?)ため、Visual C++6.0(以下VC++6.0)でプログラミングを行い、VC++6.0で作成したクラスをVB6.0で呼び出して使用したいと考えています。 インターネット上でいろいろと調べてみたのですが、その方法がわからず投稿させていただきました。VC++6.0で作成したDLLの中の関数をVB6.0で呼び出して使用する方法はわかったのですが、クラスということになると、DLLでは無理なのでしょうか? どなたか、VC++6.0で作成したクラスをVB6.0で呼び出す方法、または勉強方法(教材)などを教えていただけると助かります。 宜しくお願いいたします。

  • Ruby on Rails 「attr_accessor」 の使い方に

    Ruby on Rails 「attr_accessor」 の使い方について こんにちは。 現在、Ruby on Railsで登録画面を作成しているのですが、attr_accessorで定義した項目に対して、validationのチェックを行うと、問題が起きてしまいました。 attr_accessorで定義した項目は、DB登録の対象ではないのですが、lengthのチェック等を行う必要があり、validates_length_of等を使って入力チェックを行っています。 問題になったのは、入力があったときだけチェックをかけたいのに、入力がなくてもチェックがかかってしまうという状態になってしまうことです。 「:if => 項目?」を書いてみると、「undefined method」のエラーがでてしまいます。 どなたか対応策の分かる方がおられましたらご教授いただけないでしょうか? 下記に実際の問題箇所のモデルクラスのソースを書いておきます。  class User < ActiveRecord::Base    attr_accessor :NEW_USER_PW ← 追加したアクセサ    # 追加したアクセサに対するチェック    validates_length_of :NEW_USER_PW, :minimum=>4, :message=>"は%d桁以上を設定してくださ                 い。", :on => :update, :if => :NEW_USER_PW?  end 上記のチェック内の「:if => :NEW_USER_PW?」で落ちてしまいます。 入力がないのにチェックに引っかかるとまずいので、入力がないときだけ上記チェックを行えれば良いのですが・・・。 どうぞ宜しくお願い致します。

    • ベストアンサー
    • Ruby
  • Ruby Vectorの===変更の問題

    言語はRubyです。 Vectorにて数値を管理している都合上、まとめて計算や判定ができないかと思い、 要素に範囲オブジェクトを入れたVectorと、同じ要素数のVectorとの、 範囲内判定を実装したい為、下記のように組んでみました。 # # 全ての要素が、範囲内か判定 # def ===(v)  each2(v) { |range, x|   return false unless range === x  }  return true end Vector[(0..10), (5..8)] === Vector[3, 8]のように組めます。 しかしこの記述だと、元の===が変更されてしまう為、元の処理が使えなくなると思います。 ===が重要な処理と関係していなければ良いのですが、やはり大きく影響するのでしょうか? ヘルプで検索を掛けても記号の為、ヒットせず、どこで実装されているか分からないので質問しました。 ご教授下されば幸いです。 宜しくお願いいたします。

    • ベストアンサー
    • Ruby
  • コンストラクタで配列を指定する方法(C#)

    お世話になります。 本当に初歩な質問で申し訳ありません。 下記のようなことをしたいと思っています。 ---------------- A a = new A(new int[] s={1,2,3}); ----------------- クラスの作成時に、配列を参照型でなく渡したいのですが、 当然、上記の書き方はエラーになります。 配列をnew することなく、引数で直接渡してやる方法を 教えてください。 以上、よろしくお願いいたします。

専門家に質問してみよう