CSC/ECE 517 Fall 2009/wiki3 19 rn: Difference between revisions

From Expertiza_Wiki
Jump to navigation Jump to search
Line 31: Line 31:


== Language Examples ==
== Language Examples ==
=== [[Java programming language|Java]] ===
import java.util.* ;
class BankAccount {
public int balance(){
int depositSum = 0;
int withdrawalSum = 0;
for (int i = 0; i < deposits.size(); i++){
depositSum = depositSum + ((Integer)deposits.get(i)).intValue();
}
for (int i = 0; i < withdrawals.size(); i++){
withdrawalSum = withdrawalSum +
((Integer) withdrawals.get(i)).intValue();
}
return depositSum – withdrawalSum;
}
protected ArrayList deposits;
protected ArrayList withdrawals;
}
When looking at the code deposits.size(), the client can immediately see that deposits is an attribute (a “field” in Java terminology) and that size is a routine of class ArrayList (a “method” in Java terminology) because there is no opening and closing parentheses to access attributes whereas parentheses are compulsory for routine calls. This policy breaks the principle of Uniform Access; clients should not know whether a service is implemented by computation (routine) or by storage (attribute).
Hiding implementation from the client (i.e. hiding the fact a service is implemented by computation or by storage) provides flexibility. It is possible to change the implementation (for example, decide to use an attribute rather than a routine) at no cost for the clients. The supplier does not have to tell its clients about this change; the client code will continue to work. It would not be the case in the Java world where the client needs to know whether an operation is implemented as a “field” or as a “method” because he needs to add the corresponding parentheses. If the supplier changes the implementation, the client code would not compile anymore.


=== [[Ruby programming language|Ruby]] ===
=== [[Ruby programming language|Ruby]] ===
Line 125: Line 151:


Observation: There are many other ways to achieve the same functionality in PHP, for example making <code>x</code> <code>public</code> and accessing it directly or using magic methods <code>function __get($variable)</code>
Observation: There are many other ways to achieve the same functionality in PHP, for example making <code>x</code> <code>public</code> and accessing it directly or using magic methods <code>function __get($variable)</code>
=== [[Java programming language|Java]] ===
import java.util.* ;
class BankAccount {
public int balance(){
int depositSum = 0;
int withdrawalSum = 0;
for (int i = 0; i < deposits.size(); i++){
depositSum = depositSum + ((Integer)deposits.get(i)).intValue();
}
for (int i = 0; i < withdrawals.size(); i++){
withdrawalSum = withdrawalSum +
((Integer) withdrawals.get(i)).intValue();
}
return depositSum – withdrawalSum;
}
protected ArrayList deposits;
protected ArrayList withdrawals;
}
When looking at the code deposits.size(), the client can immediately see that deposits is an attribute (a “field” in Java terminology) and that size is a routine of class ArrayList (a “method” in Java terminology) because there is no opening and closing parentheses to access attributes whereas parentheses are compulsory for routine calls. This policy breaks the principle of Uniform Access; clients should not know whether a service is implemented by computation (routine) or by storage (attribute).
Hiding implementation from the client (i.e. hiding the fact a service is implemented by computation or by storage) provides flexibility. It is possible to change the implementation (for example, decide to use an attribute rather than a routine) at no cost for the clients. The supplier does not have to tell its clients about this change; the client code will continue to work. It would not be the case in the Java world where the client needs to know whether an operation is implemented as a “field” or as a “method” because he needs to add the corresponding parentheses. If the supplier changes the implementation, the client code would not compile anymore.


==See also==
==See also==

Revision as of 18:09, 17 November 2009

PROBLEM STATEMENT

The principle that an access (read or write) to a feature of an object should be written the same whether the feature is an instance variable or method. Look at the current Wikipedia article on the subject and expand on it. Consider the reason for this principle and try to find countervailing arguments against it. Note that since you are expanding on the current article, it is fine to lift text that is in the Wikipedia article right now.

INTRODUCTION

The Uniform Access Principle was put forth by Bertrand Meyer. It states "All services offered by a module should be available through a uniform notation, which does not betray whether they are implemented through storage or through computation." This principle applies generally to object-oriented programming languages. In simpler form, it states that there should be no difference between working with an attribute, precomputed property, or method/query.

Many languages have various degrees of support for UAP, where some of the implementations violate the spirit of UAP. The inclusion of 'properties' in some programming languages is another way to address the problem that Meyer discusses. Properties don't provide a uniform notation, but they do make the call to the method which provides a service opaque.

UAP Example

If a language allows access to a variable via dot-notation and assignment

Foo.bar = 5 //Assigns 5 to the object variable "bar"

then these operations should be the same :

//Assume print displays the variable passed to it, with or without parens
//Assume Foo.bar = 5 for now
print Foo.bar
print Foo.bar()

When executed, should display :

5
5

This allows the object to still hide information as well as being easy to access.

The same should be true for setting the data.

Foo.bar = 5
Foo.bar(5)
//These should achieve the same goal

Language Examples

Java

import java.util.* ;
class BankAccount {
…
public int balance(){
int depositSum = 0;
int withdrawalSum = 0;
for (int i = 0; i < deposits.size(); i++){
depositSum = depositSum + ((Integer)deposits.get(i)).intValue();
}
for (int i = 0; i < withdrawals.size(); i++){
withdrawalSum = withdrawalSum +
((Integer) withdrawals.get(i)).intValue();
}
return depositSum – withdrawalSum;
}
…
protected ArrayList deposits;
protected ArrayList withdrawals;
}

When looking at the code deposits.size(), the client can immediately see that deposits is an attribute (a “field” in Java terminology) and that size is a routine of class ArrayList (a “method” in Java terminology) because there is no opening and closing parentheses to access attributes whereas parentheses are compulsory for routine calls. This policy breaks the principle of Uniform Access; clients should not know whether a service is implemented by computation (routine) or by storage (attribute).

Hiding implementation from the client (i.e. hiding the fact a service is implemented by computation or by storage) provides flexibility. It is possible to change the implementation (for example, decide to use an attribute rather than a routine) at no cost for the clients. The supplier does not have to tell its clients about this change; the client code will continue to work. It would not be the case in the Java world where the client needs to know whether an operation is implemented as a “field” or as a “method” because he needs to add the corresponding parentheses. If the supplier changes the implementation, the client code would not compile anymore.

Ruby

class Foo
  attr_reader :x
  def initialize(x)
    @x = x
  end
  def squared_x
    return @x * @x
  end
end

y = Foo.new(2)
puts y.x
puts y.squared_x

This outputs:

2
4

Note how even though x is an attribute and squared_x is a parameterless method call, they are accessed the same way.

Python

The following example uses python properties.

class Foo(object):
    def __init__(self, x):
        self.setx(x)

    def getx(self):
        return self.__x

    def setx(self, x):
        if type(x) != int:
            raise ValueError('Not an integer')
        self.__x = x

    def getsquared_x(self):
        return self.x * self.x
    
    x = property(getx,setx, doc="x attribute of Foo object")
    squared_x = property(getsquared_x, doc="getter for squared x")

y = Foo(2)
print y.x
print y.squared_x

This outputs:

2
4

Python properties may be used to allow a method to be invoked with the same syntax as accessing an attribute. Whereas Meyer's UAP would have a single notation for both attribute access and method invocation (method invocation syntax), a language with support for properties still supports separate notations for attribute and method access. Properties allow the attribute notation to be used to invoke a method where that is desirable.

PHP

class Foo{
    private $x;

    function __construct($x){
        $this->x = $x;
    }

    function x(){
        return $this->x;
    }

    function squared_x(){
        return $this->x * $this->x;
    }
}

$y = new Foo(2);
echo $y->x();
echo $y->squared_x();

This outputs:

2
4

Observation: There are many other ways to achieve the same functionality in PHP, for example making x public and accessing it directly or using magic methods function __get($variable)

See also

Template:Compu-prog-stub

fi:Yhtenäinen osoitusperiaate