SitePoint Sponsor

User Tag List

Results 1 to 18 of 18

Hybrid View

  1. #1
    SitePoint Zealot johno's Avatar
    Join Date
    Sep 2003
    Location
    Bratislava, Slovakia
    Posts
    184
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    How to make attributes in Ruby private/inaccessible?

    Hi,

    Code:
    class Base	
    	def initialize
    		@test = 123
    	end
    end
    
    class Child < Base 
    	def output
    		print @test
    	end
    	
    	public :output
    end
    
    
    child = Child.new
    child.output
    Prints out 123.

    If attribute "test" is private, why I am able to access it in Child class?
    If attribute "test" is not private, what the hell am I missing?
    How do I make it really private?

    I really new to this Ruby stuff so please be polite.
    Annotations support for PHP5
    TC/OPT™ Group Leader

  2. #2
    SitePoint Guru
    Join Date
    Aug 2005
    Posts
    986
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Ruby has no private/public instance variable, they are all protected. You cannot access them from outside the class, but not because you have to access, but because there is no access. Everything goed through methods that return the values of instance variables and set them. So you can't make instance variables private. Are you coming from C#? All methods are public by default so you don't have to:
    Code:
    public :output
    Most people use:
    Code:
    class Example
      def one #this one is public
        #code...
      end
      
      private
        def two #this is private
        end
        
        def three #private
        end
      
      protected
        def four #protected
        end
        
        def five #protected
        end
        
      public
        def six #public again
        end
    end
    So every method after protected is protected until the ruby interpreter hits another modifier.

  3. #3
    SitePoint Zealot johno's Avatar
    Join Date
    Sep 2003
    Location
    Bratislava, Slovakia
    Posts
    184
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks for the reply.

    No private attributes? All protected. Check. I don't really know if this is a good thing in general, but I can't think of any counterexample at the moment so maybe yes.

    Ok but now look
    (Copy&Paste from http://www.rubycentral.com/book/tut_classes.html)
    Code:
    Protected access is used when objects need to access the internal state of other objects of the same class. For example, we may want to allow the individual Account objects to compare their raw balances, but may want to hide those balances from the rest of the world (perhaps because we present them in a different form).
    
    class Account
      attr_reader :balance       # accessor method 'balance'
    
    
      protected :balance         # and make it protected
    
    
      def greaterBalanceThan(other)
        return @balance > other.balance
      end
    end
    
    Because the attribute balance is protected, it's available only within Account objects.
    If what you say is true, it means that this code (attr_reader, protected mumbo jumbo) is simply not necessary because I can (as I demonstrated before) access the attribute directly.

    I think this example in docs is really missleading.

    No I'm not comming from C#. I am programming mostly in PHP and Java. Thank god no J2EE ;-)
    Annotations support for PHP5
    TC/OPT™ Group Leader

  4. #4
    SitePoint Wizard DougBTX's Avatar
    Join Date
    Nov 2001
    Location
    Bath, UK
    Posts
    2,498
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by johno
    Code:
    class Account
      attr_reader :balance       # accessor method 'balance'
    end
    You've got to remember that that doesn't create @balance, rather it is more a shortcut for this:

    Code:
    class Account
      def balance
        @balance
      end
    end
    So when you do protected :balance it is exactly the same thing which happens when you do protected :some_other_method.

    Though this mightbe useful:

    Code:
    class Account
      def balance
        @balance / 8
      end
    
      def balance= (val)
        @balance = val * 8
      end
      
      protected :balance, :balance=         # and make it protected
    
    
      def greaterBalanceThan(other)
        return balance > other.balance # uses self.balance instead of @blanace
      end
    end
    Douglas
    Hello World

  5. #5
    SitePoint Zealot johno's Avatar
    Join Date
    Sep 2003
    Location
    Bratislava, Slovakia
    Posts
    184
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    DOUGBTX: Yes, yes, I know it now. I am pointing finger at the online book.

    Imagine me (a Ruby wanna-learn with some OO experience) reading this

    The Song objects we've created so far have an internal state (such as the song title and artist). That state is private to those objects---no other object can access an object's instance variables. In general, this is a Good Thing. It means that the object is solely responsible for maintaining its own consistency.
    Then comes the example how to make these "private" attributes protected.

    Then I try to access them directly (by mistake) and WOW it works!

    Really misleading examples. Why on earth is there not written that attributes are protected by default. One sentence. Or maybe I am stupid and just can't find it.
    Annotations support for PHP5
    TC/OPT™ Group Leader

  6. #6
    SitePoint Zealot
    Join Date
    Jul 2004
    Location
    Oklahoma
    Posts
    119
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by johno
    DOUGBTX: Yes, yes, I know it now. I am pointing finger at the online book.

    Imagine me (a Ruby wanna-learn with some OO experience) reading this



    Then comes the example how to make these "private" attributes protected.

    Then I try to access them directly (by mistake) and WOW it works!

    Really misleading examples. Why on earth is there not written that attributes are protected by default. One sentence. Or maybe I am stupid and just can't find it.
    Well no instance of another object can access those variables. But a a subclass sure can. So yes, the variables are only protected but, the wording there isn't incorrect.

  7. #7
    SitePoint Wizard DougBTX's Avatar
    Join Date
    Nov 2001
    Location
    Bath, UK
    Posts
    2,498
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Sgarissta
    Well no instance of another object can access those variables.
    Code:
    >> class MyPrivates
    >>   def initialize
    >>     @google = 'search'
    >>     @apple = 'it'
    >>   end
    >> end
    
    >> my = MyPrivates.new
    => #<MyPrivates:0x2cfa470 @apple="it", @google="search">
    >> my.instance_variable_get(:@apple)
    => "it"
    >> my.instance_variable_get(:@google)
    => "search"
    
    >> my.instance_variables.each { |name| puts "#{name} => #{my.instance_variable_g
    et(name)}" }
    @apple => it
    @google => search
    Hello World

  8. #8
    SitePoint Wizard DougBTX's Avatar
    Join Date
    Nov 2001
    Location
    Bath, UK
    Posts
    2,498
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hmm, yes, there is some fuzzyness there. I have to say, it totally passed me by, I read that book ages ago, and whenever I see @foo, I think "private", but when I think "private" I'm really thinking "protected" - I've never really seen the point of private. And besides, bar.instance_variables

    Douglas
    Hello World

  9. #9
    SitePoint Guru
    Join Date
    Aug 2005
    Posts
    986
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Well, it might be so natural for Ruby programmers that all attibutes act like this, and besides, attributes are not exactly "protected". There is just no way of accessing them from the outside. It is a different scope. You can only send messages (call methods) to objects.

  10. #10
    SitePoint Guru silver trophy Luke Redpath's Avatar
    Join Date
    Mar 2003
    Location
    London
    Posts
    794
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Interesting choice of class name

  11. #11
    SitePoint Evangelist
    Join Date
    Jun 2004
    Location
    California
    Posts
    440
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Luke Redpath
    Interesting choice of class name
    Off Topic:

    Excuse me but... HAHAHAHAHHAHA didn't notice until you said so Oh well I should grow up. hehe... hehehehe.

  12. #12
    SitePoint Guru silver trophy Luke Redpath's Avatar
    Join Date
    Mar 2003
    Location
    London
    Posts
    794
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Nothing wrong with a bit of childish humor from time to time...

    Anyway, if you really wanted to make your instance variables private, could you not just do:

    Code:
    class YourPrivates
      private :instance_variables
    end

  13. #13
    SitePoint Zealot johno's Avatar
    Join Date
    Sep 2003
    Location
    Bratislava, Slovakia
    Posts
    184
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Luke Redpath
    Nothing wrong with a bit of childish humor from time to time...

    Anyway, if you really wanted to make your instance variables private, could you not just do:

    Code:
    class YourPrivates
      private :instance_variables
    end
    No, because attributes are can be accessed directly from subclass. You don't have to make any setters/getters.
    Annotations support for PHP5
    TC/OPT™ Group Leader

  14. #14
    SitePoint Guru silver trophy Luke Redpath's Avatar
    Join Date
    Mar 2003
    Location
    London
    Posts
    794
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by johno
    No, because attributes are can be accessed directly from subclass. You don't have to make any setters/getters.
    I meant from outside of the class. See the example above on how to access instance variables from outside of the class. By making the instance_variables() method private, you should disable access to them that way.

  15. #15
    SitePoint Zealot
    Join Date
    Nov 2004
    Location
    Yakima WA.
    Posts
    100
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    There isn't a way to make things entirely private or protected in ruby right now. No matter what you do to try to protect something, you can always use send or __send__ to access private or protected vars or methods.

    Check these commands for more info:

    $ ri send
    OR
    $ ri __send__

    Cheers-
    -Ezra

  16. #16
    SitePoint Wizard DougBTX's Avatar
    Join Date
    Nov 2001
    Location
    Bath, UK
    Posts
    2,498
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by johno
    How do I make it really private?
    Here's a quote I just came across:

    I started programming by learning C++. I got up to the part about public, private, protected, friend, etc... got very annoyed by the unnecessary bureaucracy of it all and dropped the language... If I can't trust the programmers around me not to muck around in my guts without good reason, I can't trust them at all. And if they're willing to perform that bad practice, they'll probably do more anyway. It's not worth worrying about.

    source

    Quote Originally Posted by Luke Redpath
    I meant from outside of the class. See the example above on how to access instance variables from outside of the class. By making the instance_variables() method private, you should disable access to them that way.
    It's a bit of a moot point, considering we have open classes.

    Code:
    >> class Foo
    >>   def initialize
    >>     @foo = "bar"
    >>   end
    >> end
    => nil
    >> f = Foo.new
    => #<Foo:0x2cfbfb8 @foo="bar">
    >> def f.foo
    >>   @foo
    >> end
    => nil
    >> f.foo
    => "bar"
    Oh, and good to know somone actually reads the code I post

    Douglas
    Hello World

  17. #17
    SitePoint Zealot johno's Avatar
    Join Date
    Sep 2003
    Location
    Bratislava, Slovakia
    Posts
    184
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    DOUG: There is absolutely some really rational thinking in that citation. I've never thought of access control this way. On the other hand, I think in some cases it can be better if you declare some variables as protected (or whatever that means in ruby). Encapsulation is a good thing in general. You don't need to know the internals of classes if you are using it. It would be only missleading. We all dream about nice APIs. So why polute them with unneccessary 'internal' attributes?
    Annotations support for PHP5
    TC/OPT™ Group Leader

  18. #18
    SitePoint Wizard DougBTX's Avatar
    Join Date
    Nov 2001
    Location
    Bath, UK
    Posts
    2,498
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    That's what I'm thinking.

    And if you take "protected" to mean "you've got to put in noticeable effort when you are outside," and "public" to mean "always easy to get at," then I think that covers it.

    Douglas
    Hello World


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •