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

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

ただいまの
回答率

90.47%

  • Ruby

    7922questions

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

  • オブジェクト指向

    293questions

    オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。

  • インターフェース

    26questions

    インターフェイスという用語はハードウェア・ソフトウェアの両方に使うことができます。 一般的に、インターフェイスは内部処理の詳細を見せないように設定されます。オブジェクト指向プログラミングにおいて、インターフェイスはabstractクラスとして定義されます。

【Ruby】公開メンバへのアクセスを、特定のクラスに対して制限したい

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,033

topo

score 222

あるクラスの公開メンバを、特定のクラスには公開したくない(=アクセスさせたくない)場合、Rubyではどのような方法があるのでしょうか。

JavaやC#のような静的型付け言語の場合は、以下のように、間にアクセス専用のインタフェースを挟んで解決しています。

public class Accessed implements AccessLimiter{
    private int _data = 100;

    public int getData() {
        return _data;
    }
    
    public int calc(int a, int b) {
        return a + b + _data;
    }
    
    public String calcAsString(int a, int b) {
        return (a + b + _data).toString();
    }
}

public interface AccessLimiter {
    int getData();
    int calc(int a, int b);
}

public class Accessor {
    private AccessLimiter _target;
 
    public Accessor(Accesslimiter target) {
        this._target = target;
    }

    public int[] access(int a, int b) {
        int[] result = new int[3];
        result[0] = a;
        result[1] = b;
        result[2] = _target.calc(a, b);

        return result;
    }
}
この場合、calcAsStringは基本的にはpublicメソッドですが、責務や関連の都合から、Accessorには公開したくない(=Accessorには利用させたくない)メソッドです。

しかし、Rubyにはインタフェースが存在しないため、同様の方法を使用できません。委譲によるAdapterパターンを使うしか無いのかな、と現在考えていますが、他に何か有用な手段はRubyに存在するのでしょうか。
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

0

Accessor の initialize で渡された Accessed のインスタンの calcAsString のメソッドを上書きしてエラーが発生するようにしてしまうという方法ではダメですか?

# coding: utf-8

class Accessed
  def initialize(data = 100)
    @data = data
  end

  def calc(a, b)
    a + b + @data
  end

  def calcAsString(a, b)
    (a + b + @data).to_s
  end
end

class Accessor
  def initialize(target)
    @target = target.clone
    def @target.calcAsString(a, b)
      fail "can not call"
    end
  end

  def access(a, b)
    [a, b, @target.calc(a, b)]
  end

  def method_A(a, b, accessed)
    accessed.calcAsString(a, b)
  end

  def method_B(a, b)
    @target.calcAsString(a, b)
  end
end

accessed = Accessed.new
accessor = Accessor.new(accessed)

p accessed
p accessed.calcAsString(1, 2)
p accessor.access(10, 20)
p accessor.method_A(10, 20, accessed)
# => これはエラーにならない。

p accessor.method_B(10, 20)
# => 実行時にエラーになる。
#    Accessor 中の @target#calcAsStringをオーバーライドしてエラーになるようにしているので。

実行例:
$ ruby  1.rb
#<Accessed:0x007ff3dc0fa190 @data=100>
"103"
[10, 20, 130]
"130"
1.rb:21:in `calcAsString': can not call (RuntimeError)
    from 1.rb:34:in `method_B'
    from 1.rb:47:in `<main>'

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/09/06 21:28 編集

    ご回答頂き、ありがとうございました。
    このような方法があるのですね、知りませんでした。ただ、「アクセスしてはいけないメンバ」については、そもそもアクセス自体できないようにしたい(=メンバへの参照自体を禁止したい)という感覚があり、違和感を覚えてしまいます……。
    動的型付けの場合は、呼び出し元の方で制限を設ける等して注意を払うしかないのでしょうか。

    キャンセル

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

  • ただいまの回答率 90.47%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • Ruby

    7922questions

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

  • オブジェクト指向

    293questions

    オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。

  • インターフェース

    26questions

    インターフェイスという用語はハードウェア・ソフトウェアの両方に使うことができます。 一般的に、インターフェイスは内部処理の詳細を見せないように設定されます。オブジェクト指向プログラミングにおいて、インターフェイスはabstractクラスとして定義されます。