The One-Way-In, One-Way-Out Principle

In most modern object-oriented languages such as Java and C#, encapsulation and information hiding are not rigorously enforced. In Smalltalk, on the other hand—the most famous and influential object-oriented language—encapsulation and information hiding are fundamental principles: If you send a variable x to a method y and the value of x is changed inside y, you cannot obtain the changed value of x from outside the method—unless the method explicitly returns that value.

Usually, Ruby adheres to this principle: Arguments go into a method, but any changes made inside the method cannot be accessed from the outside unless Ruby returns the changed value:

hidden.rb

def hidden( aStr, anotherStr )
    anotherStr = aStr + " " + anotherStr
    return anotherStr.reverse
end

str1 = "dlrow"
str2 = "olleh"
str3 = hidden(str1, str2)
puts( str1 )    #=> dlrow
puts( str2 )    #=> olleh
puts( str3 )    #=> hello world

In the previous code, the string value of the second object, str2, is received by the anotherStr argument of the hidden method. The argument is assigned a new string value and reversed. Even so, neither of the original variables, str1 or str2, is changed. Only the variable assigned the return value, str3, contains the changed “hello world” string.

It turns out that there are occasions when arguments passed to a Ruby method can be used like the “by reference” arguments of other languages (that is, changes made inside the method may affect variables outside the method). This is because some Ruby methods modify the original object rather than yielding a value and assigning this to a new object.

For example, there are some methods ending with an exclamation mark that alter the original object. Similarly, the String append method << concatenates the string on its right to the string on its left but does not create a new string object in the process: So, the value of the string on the left is modified, but the string object itself retains its original object_id.

The consequence of this is that if you use the << operator instead of the + operator in a method, your results will change:

not_hidden.rb

def nothidden( aStr, anotherStr )
    anotherStr = aStr << " " << anotherStr
    return anotherStr.reverse
end

str1 = "dlrow"
str2 = "olleh"
str3 = nothidden(str1, str2)
puts( str1 )      #=> dlrow olleh
puts( str2 )      #=> olleh
puts( str3 )      #=> hello world

In the previous code, the anotherStr argument is concatenated with a space and the aStr argument using <<, and the resulting string is reversed when returned. If information hiding were rigorously enforced, this might be expected to produce the same results as in the previous program—that is, str1 and str2 would remain unchanged. However, the use of << has had profound effects because it has caused the modifications made to the aStr argument inside the nothidden method to change the value of the str1 object outside the method.

This behavior, incidentally, would be the same if the nothidden method were placed into a separate class:

nothidden2.rb

class X
    def nothidden( aStr, anotherStr )
        anotherStr = aStr << " " << anotherStr
        return anotherStr.reverse
    end
end
ob = X.new
str1 = "dlrow"
str2 = "olleh"
str3 = ob.nothidden(str1, str2)
puts( str1 )    #=> dlrow olleh

This shows that, in certain cases, the internal implementation details of an object’s methods may accidentally alter the code that calls it. It is generally safer to make implementation details hidden; otherwise, when code is rewritten inside a class, the changes may have side effects on code that uses that class.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.141.35.185