人に聞けない痔の悩み、これでスッキリ >>

プログラミング言語のRubyでプログラムを作っていて疑問に思った事がありますので
どなたかご存知の方が居れば教えてください。

Rubyにおいては同じクラス名やモジュール名であっても
モジュール内に対象クラスやモジュールを定義する事で

「モジュール名::クラス名」等と言う参照が可能になっていますよね

そこで気になったのですが、同名のクラスAとモジュールAがある場合に
(つまりクラスAの名前=モジュールAの名前)

class モジュールA::クラスB
 # コンストラクタ
 def initialize
  @prop = クラスA.new
 end
end

等と記述すると、コンストラクタの内部の記述において
クラスAの名前とモジュールAの名前が競合するので、クラスBの生成時にエラーが発生します。

この様なケースにおいて、コンストラクタの内部でクラスAのインスタンスを
正しく生成する方法はあるのでしょうか?

勿論前提として、クラスAは他のモジュールに含まれたクラスではありません。

Javaの様にパッケージ概念があって、全てのクラスについて何らかのパッケージに所属している等の
仕組みが無いので、時々この様な命名をしてしまい困る事があるので
この様なケースを回避する方法についてご存知の方が居れば、教授ください。

よろしくお願いします。

このQ&Aに関連する最新のQ&A

A 回答 (5件)

Rubyのモジュールやクラスは定数です。

同じ名前空間で同じ名前の定数を定義することはできません。
ですから、

class A
end

module A
end

とすると、A is not a module というエラーになります。
これは、クラスとして定義した A をモジュールとして開き直そうとしています。

但し、この class A と module A が別々のファイルに記述されていて、
class A、または。module A を呼び出した場合エラーにはなりません。
なぜなら、Ruby は定数の探索をして最初に到達したものを採用するからです。
そしてご質問のケースの場合、Ruby は module A を見つけたがクラスではないので、エラーを出しています。

a = A # => エラーにはならない。

a = A.new # => エラーになる。


つまり、同一の名前空間に同じ名前のクラスとモジュールを記述することはコーディングミスです。
ファイルが分かれていれば、呼び出さない限りはエラーにはなりませんが、
これではまともなプログラムが書けません。

同じ名前を使いたければ、名前空間を分けるようにしましょう。

例えば、


# coding: utf-8

module Dog
 class Voice
  def play
   puts "わん"
  end
 end
end

module Cat
 module Voice
  def cry
   puts "にゃあ"
  end
 end
end

tama = "ねこ"

tama.extend Cat::Voice

johns_voice = Dog::Voice.new

tama.cry #=> "にゃあ"
johns_voice.play #=> "わん"



のようにします。
    • good
    • 0

No.1,2です。


モジュールにせずにクラスの中にクラスを作るのはいかがでしょうか。
class A
def initialize
end

class B
def initialize
@prop = A.new
end
end
end

p A::B.new
No.1にも書きましたが、もしclass A::Aがあれば
::A.newで区別できます。
    • good
    • 0

class クラスA


 # コンストラクタ
 def initialize
 end
end

module モジュールA
 class クラスB
  # コンストラクタ
  def initialize
   @prop = クラスA.new
  end
 end
end
上記でエラーになるということですが、このエラーを解消するために、
module 汎用モジュールA
class クラスA
 # コンストラクタ
 def initialize
 end
end
end
としては、いかがでしょうか。
つまり class クラスAを汎用モジュールの名前空間に閉じ込めます。
以下は、こちらで実行したサンプルソースです。
------------------------------------------
# coding:WINDOWS-31J
module Common
class NameA
def initialize
p "Class NameA initialize"
end
def put
p "put A"
end
end
end
module NameA
class NameB
def initialize
p "Class NameB initialize"
@prop = Common::NameA.new
end
def put
@prop.put
end
end
end

a = NameA::NameB.new
a.put
---------------------------------------
実行結果
"Class NameB initialize"
"Class NameA initialize"
"put A"
---------------------------------------
実行環境は
windows7
1.9.3p374 (2013-01-15) [i386-mingw32]
です。
    • good
    • 0

実際のプログラムを書いてもらえればわかりやすいのですが、


module A
class B
def initialize
@prop = A.new
end
end
end

class A
end

p A::B.new
のような場合でしょうか?
この場合はA.newでエラーが出るのではなく、9行目のclass Aでエラーが出ます。
classとmoduleで同じ名前が使えないということです。(この場合はclass Aとmodule A)
名前の付け方に注意する必要があります。
    • good
    • 0

ちょっと質問の意味が分からなかったのですが


module ModuleA
class ClassA
end

class ClassB
def initialize
@prop = ClassA.new
end
end
end
p ModuleA::ClassB.new
を実行させると、@propの中にはModuleA::ClassAのインスタンスが代入されます。
自分が属しているモジュールの中にClassAがあるのでModuleA::ClassAとなりますが、もし無ければモジュールの外側にClassAがないか探します。モジュールの外側の場合は::ClassA.newで区別できます。

それとも
module A
class A
end

class B
def initialize
@prop = A.new
end
end
end
p A::B.new
の場合でしょうか、これも全く問題はないですが。

こんな場合でしょうか
module A
end
class A::A
end

class A::B
def initialize
@prop = A::A.new
end
end
p A::B.new
の場合は
@prop = A.new
とした場合にはエラーになります。
このような書き方はあまりしないように思います。

この回答への補足

質問が判り辛くて申し訳有りません。
私が回避したいケースは下記の様なケースです。

  クラスAの名前=モジュールAの名前

と言う状況において

class クラスA
 # コンストラクタ
 def initialize
 end
end

module モジュールA
 class クラスB
  # コンストラクタ
  def initialize
   @prop = クラスA.new
  end
 end
end

と言うコードのクラスBのインスタンスを生成する際に

   @prop = クラスA.new

の処理のタイミングで、クラスAをモジュールAと解釈してしまい
エラーが発生するのですが
それを回避する方法があれば教えて頂きたいと言う質問でした。

つまりこのクラスAと言うのは、どのモジュールにも所属していないクラスであり、ki073さんの回答していただいた最後のケースに近い状況でのエラーの回避です。

補足日時:2013/02/17 21:46
    • good
    • 0

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

QRuby 改行文字の挿入

こんにちは。
Rubyの質問です。
htmlの文章にrubyで改行文字を挿入してそれを認識させたいのですが、
htmlの文章内に¥nを挿入しても読み込んだ際にうまく認識してくれませんでした。

何か他に方法があるのでしょうか。
ご教授の程よろしくお願い致します。

Aベストアンサー

どのようにして\nを挿入したのか、不明ですが、エディタを使用して行った前提で回答です。
改行コードを埋め込む場合は、\nを挿入したい位置で、Enterキーを押下してください。
それで、見かけ上、2行になれば、そこに改行コードが埋めこまれたことになります。

尚、通常は\nの文字そのものは、\とnの2文字にすぎません。
ruby のスクリプトでそれを"\n"のようにダブルクオートでくくった場合、それをrubyが改行コードとして扱う
という特別の約束があります。

ですので、エディタで行なう場合は、実際の改行コードを埋め込まないといけません。

QClassの中のClass定義について

Classの中のClass定義について

主にWindows環境でrubyを使用しているライトユーザーです。
ネットでソースを拝見していると、Class定義の中に更にClass定義がされているプログラムをみることがあります。以下のような感じですね。

Class Foo
 Class Bar
 ……
 end
……
end

このようにClass定義を他のClass定義の中に書くのは、どのような理由によるのでしょうか?
素朴な疑問です、ご教示いただければ嬉しいです。

Aベストアンサー

名前空間ですね。

class Foo
 class Bar
 ……
 end
……
end
class Hoge
 class Bar
 ……
 end
……
end
class Bar
 ……
end

だと、それぞれの、Barクラスは別物で、それぞれFoo::Bar、Hoge::Bar、Barという名前のクラスになります。ただし、クラスFooの中ではFoo::BarはBarと略記できるし、Hogeの中ではHoge::BarをBarと略記出来ます。

例えば、Fooクラスの中でしか利用しないクラスがあった場合に、他のクラスと名前の衝突を気にすることなく名前を付けることが出来るわけです。ただし、Fooクラス外からもFoo::Barのように利用することが出来るので、Fooクラス内に隠蔽できるわけではないですが。

定数などもクラスの中で定義すれば、Foo::CONSTNAME のような定数が出来ます。

Qインスタンス内から自分のクラス名を取得する方法

クラスインスタンス内から自分のクラス名を取得しようと思うと、self.class.nameで取得できますが、type.nameでも取得できます。
しかし、typeは非推奨メソッドとなっているため、警告が出て、このままでは使用することができません。

素直にself.classを使えばいいのかもしれませんが、selfのワンクッションがどうにも気に入りません。

スマートな記述方法あったら教えて下さい。

# self.class.nameを使用する場合
class MyClass
 def print_classname
  puts self.class.name
  # puts class.name これはエラー
 end
end

# type.nameを使用する場合
class MyClass2
 def print_classname
  puts type.name # これはdeprecatedの記述で警告が出る
 end
end

Aベストアンサー

self を書きたくないということなら、
alias :xclass :class
しておいて、
xclass.name
するくらいしかないと思います。スマートとは思いませんけど。

逆に、インスタンスメソッド定義の中で、class以外のメソッド呼び出しの時もselfを省略しないで書くことにすれば、全部統一が取れます。

QrubyでC言語のexitにあたる構文は?

現在、C言語のプログラムをrubyに書き換えています。

そこで、C言語のexitに当たるrubyの構文、もしくは、
文法が見つからず、困ってます。
(ある条件になったら、強制的にrubyの実行を
 停止させたいのですが、、、)
(__END__ですか?)

詳しい方が居ましたら、ご指南下さい。

Aベストアンサー

#2です。
>exit のあとの数字について詳しく知らないので、
>教えていただけたら幸いです。
exitのあとの数字は終了コードといって、どのような状態で、このプログラムが終了したかを、呼び出しもとに伝える為のものです。
この値は、呼び出し元と、呼び出される側(このプログラム)との決め毎なので、どのようにきめてもかまわないのですが、
ふつうは、終了コード:0で終了したときが、正常終了にします。
それ以外の値は、異常終了を示す値にします。

この終了コードは、なにかのサブルーチンを作ったときの、戻り値に似ています。
サブルーチンの戻り値は、呼び出しもとと呼び出される側(サブルーチン側)とで、自由にきめて良いのですが、
通常は、正常:0、以外は、それなりの異常にしますよね。

Qファイルの特定行を取り出したい.

こちらのサイトを参考にさせていただきました.
http://www.namaraii.com/rubytips/?%A5%D5%A5%A1%A5%A4%A5%EB%A5%A2%A5%AF%A5%BB%A5%B9

やりたいことはファイルにアクセスして2行目,3行目の文字列をとってくることです.

===foo===
hoge
hige
foobar

File::open("foo") {|content|
 puts content.readlines[1]
 puts content.readlines[2]
}

このようなプログラムだと,
hige
nil
となります.ですが,以下のように分割するとうまくいきます.
File::open("foo") {|content|
 puts content.readlines[1]
}
File::open("foo") {|content|
 puts content.readlines[2]
}
hige
foobar

できればopenは一回だけで済ませたいのですが可能でしょうか?
Ruby初心者なのでくだらない質問かもしれませんが,ご教授ねがいます.

こちらのサイトを参考にさせていただきました.
http://www.namaraii.com/rubytips/?%A5%D5%A5%A1%A5%A4%A5%EB%A5%A2%A5%AF%A5%BB%A5%B9

やりたいことはファイルにアクセスして2行目,3行目の文字列をとってくることです.

===foo===
hoge
hige
foobar

File::open("foo") {|content|
 puts content.readlines[1]
 puts content.readlines[2]
}

このようなプログラムだと,
hige
nil
となります.ですが,以下のように分割するとうまくいきます.
File::open("foo") {|content|
 puts c...続きを読む

Aベストアンサー

No3です。

>Rubyのみ初心者です.

よかった。

>>確認2:readlinesというメソッドはどういう機能を持ったメソッドだと思っていますか?

>ファイルの内容が一行ずつ入った配列だと思ってます

ファイルを行の配列のようにアクセスできるメソッドと思っているのなら間違いです。
ファイルから全データを読み込んで、それを配列の形で返すメソッドです。したがって、呼び出したことで、該当ファイルのファイルポインタ(ファイル中で次に読み取る文字位置)は末尾のEOFの所に行ってしまいます。二回目の呼び出しで、EOFに達したファイルを再度読むことになるので空が返ります。具体的には配列なので [] が返ります。

他の方がお書きのように、呼び出し結果の配列オブジェクトを保持しておいて、以降はそれをつかうといいです。

Qrequireするファイルのパス

プログラミングの知識はほぼ皆無なのですが、仕事でRUBYを使わなければならなくなり、オープンソースを弄っているところです。

rbファイルの記述に

require '○○'

とあるのですが、判らなかったので無視して実行してみたところ、

C:/Ruby193/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `require': cannot loa
d such file -- ○○ (LoadError)
from C:/Ruby193/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `require
'
from makeindex.rb:2:in `<main>'

というエラーが出ました。

○○ファイルを色々なディレクトリに置いてみたのですが、どれも同じエラーでした。
一般的に、○○ファイルは何処に置くべきなのでしょうか。

尚、環境は以下の通りです。
WindowsXP
RUBY 1.9.3
「require '○○'」の記述があるrbファイルの場所 c:\a
rbファイルはカレントディレクトリをaにしてから実行

プログラマーの方からすれば意味不明な質問かも知れませんが、ネットで調べてみてもさっぱり判らなかったので質問させて頂きました。
宜しくお願いします。

プログラミングの知識はほぼ皆無なのですが、仕事でRUBYを使わなければならなくなり、オープンソースを弄っているところです。

rbファイルの記述に

require '○○'

とあるのですが、判らなかったので無視して実行してみたところ、

C:/Ruby193/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `require': cannot loa
d such file -- ○○ (LoadError)
from C:/Ruby193/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `require
'
from makeindex.rb:2:in `<main>'

というエラーが出ました。

...続きを読む

Aベストアンサー

カレントディレクトリがロード対象のパスから外れているようですね。

1.○○.rbをスクリプトファイルと同じ場所に置いた場合は、オプションでカレントディレクトリを追加する
> ruby -I. foo.rb


2.スクリプトファイル内でパスを追加する
$LOAD_PATH.push('.') # この行をrequreの前に追加
require '○○'


3.あるいは既に定義されているパスに○○.rbを置くとか
パスの確認は以下でできます。
> ruby -r pp -e"pp $LOAD_PATH"


こんな感じでどうでしょうか。

QInner join と Left joinの明確な違いは?

Inner join と Left joinの違いがよくわかりません。
教えてください。

Aベストアンサー

出てくる結果が違います。

テーブル1のフィールド1に、






が、

テーブル2のフィールド1に、






が入力されている場合、

SELECT [テーブル1].[フィールド1], [テーブル2].[フィールド1]
FROM テーブル1 LEFT JOIN テーブル2 ON [テーブル1].[フィールド1]=[テーブル2].[フィールド1];
では、結果は、
テーブル1.フィールド1 テーブル2.フィールド1
1               1
2               2
3               3
4               NULL
5               NULL
6               NULL
の6レコードが出力されますが、

SELECT [テーブル1].[フィールド1], [テーブル2].[フィールド1]
FROM テーブル1 INNER JOIN テーブル2 ON [テーブル1].[フィールド1]=[テーブル2].[フィールド1];
では、結果は、
テーブル1.フィールド1 テーブル2.フィールド1
1               1
2               2
3               3
の3レコードしか出力されません。

出てくる結果が違います。

テーブル1のフィールド1に、






が、

テーブル2のフィールド1に、






が入力されている場合、

SELECT [テーブル1].[フィールド1], [テーブル2].[フィールド1]
FROM テーブル1 LEFT JOIN テーブル2 ON [テーブル1].[フィールド1]=[テーブル2].[フィールド1];
では、結果は、
テーブル1.フィールド1 テーブル2.フィールド1
1               1
2               2
3           ...続きを読む

Qポートの80と443

こちらのサービス(https://secure.logmein.com/)を利用すると、インターネットを見られるサーバーのポートの80と443が空いていればルータやファイアウォールに特段の設定なく外部からサーバーを操作できるそうですが、逆にサーバーのポートの80や443を空けることには何か危険性があるのでしょうか。

Aベストアンサー

ポート80は一般的なHTTP、ポート443はHTTPSです。
この2つのポートがあいていなければインターネット接続(WEBブラウジング)は出来ません。
ですから、ほとんどのファイアウォールでこのポートは開いています。(インターネット接続を制限している社内LANでは当然閉じていますが)

ちなみに、よく使うポートとしてはFTPで20、21、SMTP(送信メール)で25、受信メールPOP3で110あたりです。セキュリティポリシー上、この辺は制限される事も多いですが、HTTP 80、HTTPS(暗号化用)443は通常閉じません。


危険性?
WEBプロトコルを使ってFTP的なファイル転送(WebDAV)やVPN等も出来るようになっています。当然そこにはある種の危険はつきものですが、WEBブラウジングに伴う危険と大きく変わりません。ウィルス等に感染していればこの2つのポートだけでも相当危険でしょうね。

参考まで。

Q配列に複数の値があるか簡潔に判断する方法

hairetu = [1,2,3,4,5]

という配列があった時
3と4が含まれているかを判断するには

if hairetu.include?(3) && hairetu.include?(4)
 p "3と4が含まれている"
end

と書けばよいのですが
条件が増えたら、見にくくなってしまいます。
そういった理由で

if hairetu.include?(3,4)

if hairetu.include?(3 or 4)
という具合に、短く書く方法があれば
ご教授お願い致します。

Aベストアンサー

この場合はArray#-が単純で良いと思います。
([3, 4] - hairetu).empty?

Qidを使わずにonclickで自身の要素取得

javascriptで
<a href="XXX.XXX" title="ゴール" onclick="element()">test</a>
function() {
idを使わずにここにtitle属性のゴールを習得する方法を記述したいのですが、わかりません
よろしくお願いします
}

Aベストアンサー

こんにちは。


==== HTML
<a href="" title="ゴール" onclick="getTitle(this);return false;">test</a>
<a href="" title="スタート" onclick="getTitle(this);return false;">test2</a>


==== JavaScript
function getTitle ( obj ) {
var title = obj.getAttribute('title');
alert ( title );
}

こういうことでしょうか。
違っていたらすみません。


人気Q&Aランキング