Ziehen Sie nicht die Ruby-Methoden instance_eval () und send () negieren die Vorteile der privaten Sicht?

StackOverflow https://stackoverflow.com/questions/896606

Frage

w = Widget.new # Create a Widget
w.send :utility_method # Invoke private method!
w.instance_eval { utility_method } # Another way to invoke it
w.instance_eval { @x } # Read instance variable of w

am Beispiel der Suche, über den auf die Widget-Klasse bezieht (siehe unten), verletzen die Sende- und instance_eval Methoden all von privaten und geschützten Sichtbarkeits gebotenen Schutz. Wenn ja, warum mit privatem und geschützten Zugang in Ruby stört überhaupt, da es keine Garantie, dass Ihre Definitionen geehrt werden?

class Widget
  def x # Accessor method for @x
   @x
  end
  protected :x # Make it protected
  def utility_method # Define a method
   nil
  end
  private :utility_method # And make it private
end
War es hilfreich?

Lösung

Wenn Sie wirklich wollen Instanzen Widget schützen, können Sie dies tun (und ein paar andere Sachen, die Code hier ist nicht eine komplette Sicherheitslösung, lediglich indikativ):

class Widget

  def some_public_method
    ...
  end

  private

  def utility_method
    ...
  end

  def send(method, *args, &block)
    raise NotImplementedError.new('Widget is secure. Stop trying to hack me.')
  end

  def instance_eval(&block)
    raise NotImplementedError.new('Widget is secure. Stop trying to hack me.')
  end

  class <<self
    private
    def class_eval(&block)
      raise NotImplementedError.new('Widget is secure. Stop trying to hack me.')
    end
  end
end

Widget.freeze

Andere Tipps

Rubin glaubt Ihnen die Macht zu geben, um zu tun, was Sie wollen. es macht es einfach nicht leicht zu versehentlich Sie den Fuß vom schießen - wenn Sie die privaten Erklärungen zu unterlaufen wollen, müssen Sie Syntax verwenden, die deutlich macht, so Sie tun. beachten Sie, dass die Person schließlich zu entscheiden, was der Code sollte oder nicht tun soll, eine Bibliothek, nicht die Person schreibt es die Person ist.

Ich kann nicht sagen, wegen der niedrigen rep: /.

Bitte senden Sie Neudefinition es keine Verwendung, da send ist nur der gemeinsame Name für __ senden __ (das ist zu unterstreichen, unterstreichen, "senden", unterstreichen, unterstreichen), die die Methode der tatsächlichen Durchführung Nachricht sendet. Neudefinition jede __ Methode __ wird nicht empfohlen. Zusätzlich kann die andere Person auch die Klasse wieder öffnen und die Definition zurückkehren:

class Widget
  def send(method, *args, &block)
    super
  end
  #and so on
end

In Ruby 1.9 ist das Verhalten etwas anders:. #Send eigentlich ehrt Sichtbarkeit, __ __ senden nicht

Private in Ruby hat mehr von einem deklarativen Zweck: Methoden als privat deklariert sind ein Implementierungsdetail und nicht ein API Detail. Sie sind nicht eine Nachricht von außen durch Zufall senden dürfen. Aber jeder kann immer noch umgehen mit Nachdruck, dass die Restriktion, wenn sie es für richtig - auf eigene Rechnung.

Am allerwenigsten auszudrücken, was die öffentliche API der Widget-Klasse ist.

Die Botschaft ist: nicht die Mühe machen

.

Rubin, wie Python, saugt absolut bei Sandbox. Wenn Sie versuchen, um etwas zu sperren, sind die Chancen wird es immer ein Weg sein, um um es zu bekommen. Die Vielzahl der Möglichkeiten, ein eigenes Attribut in Ruby beweist meinen Punkt.

Warum? Weil sie dazu bestimmt sind, so zu sein. Beide Sprachen sind so konzipiert, dass sie mit um zur Laufzeit stocherte werden kann - es ist, was ihnen ihre Macht gibt. Durch die Versiegelung der Klasse, werden Sie andere von der Macht zu berauben, die Rubys metaprogramming bietet.

Java hat Reflexion. C ++ hat Zeiger. Auch Haskell hat unsafePerformIO. Wenn Sie Ihr Programm schützen möchten, müssen Sie es auf der Betriebssystemebene zu schützen, nicht die Sprache.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top