CSC/ECE 517 Fall 2011/ch2 2b sa
Access Control in Object Oriented Languages
- Each Object Oriented Language has its own way of implementing Access Control .This page discusses the various ways in which Access control is implemented in some of the Object Oriented Languages.
Access Control
Access control in programming languages provides the programmer the ability to define standards that are needed to hide the implementation of the modules from the public interface.Access control provides the programmer ,the ability to prevent under privileged users from access to internal components of a program and restricts them from changing the data within the component to an inconsistent state(i.e elements(members functions and variables) within a program(class)) there by protecting the integrity of the components .This concept of hiding the information in object oriented languages is called Encapsulation.
Access Control in Ruby
Access control in ruby is achieved using the following access modifiersfor the methods.
- public :The methods that are declared as public can be accessed by any object belong to the class .
- private :The methods that are declared as private can only be invoked in the context of the current object.
- protected :The methods that are declared as protected can be invoked by the objects of both the class and the sub-classes.
In Ruby these modifiers only apply to the methods but not the instance variables.
Public Methods in Ruby
Public methods in ruby can be accessed by any object or instance of a Class and its Sub-classes. Declaration of public methods:
class A def method puts "hello" end end
class A def method puts "hello" end public :method end
Private Methods in Ruby
private methods in Ruby can only be invoked by the current object in question and one cannot invoke other object's private methods. In Ruby private methods are not private to the class but they are private to the objects. No method is perfectly private in Ruby.
Declaration of Private methods
class A private def method end end class A def method end private :method end
An example to show that private methods in Ruby can only be invoked by the current object in context.
class A def method puts "I am a private method" end def pubm method A.new.method // It gives an error because pubm method is called in the context of object 'a',so only object 'a' can puts "I am a public method" invoke the private method but not the new object. end private :method end class B def m1 method //private methods of the base class can be accessed by the sub class end end a=A.new b=B.new a.pubm a.method //gives an error b.m1
Protected Methods in Ruby
protected methods are visible in both the base class as well as the sub-classes(i.e they can be invoked by the objects of both the class and its sub-classes).
Declaration of protected methods is ruby.
class A protected def method end end class A def method end protected :method end
Unlike private methods ,In Ruby protected methods can be called with an explicit receiver.
class A def method puts "I am a protected method" end def pubm method A.new.method // It does not give an error because in the context of the current object, another object belonging to same puts "I am a public method" class can invoke the protected method . end protected :method end class B def m1 method //protected methods of the base class can be accessed by the sub class. end end a=A.new b=B.new a.pubm a.method //gives an error b.m1
In Ruby both the private as well as the protected methods can be accessed from outside the class using send method.
class A def privateMethod puts "I am a private method" end def pubm privateMethod A.new.method // It does not give an error because in the context of the current object, another object belonging to same puts "I am a public method" class can invoke the protected method . end private :privateMethod end a=A.new a.method // gives an error a.send(:privateMethod) // prints "I am a private method" a.send :privateMethod // prints "I am a private method" a.method(:privateMethod).call // prints "I am a private method"
Access Control in C++
Controlling Access to the Member Data and Member Functions
In C++ one can restrict the level of access control on the member data a nd function using the access specifiers public,private and protected. A constructor should never be declared as private. Access control is applied to all the names uniformly.
Controlling the Level of accessibility of Base class and its Members
If a class is inheritedusing a public access specifier than the public members of the base class are inherited as the public members of the derived class and protected members of the base class are inherited as the protected members of the derived class.If a class is inherited using a private access specifier than both the public and protected members of the base class become the private members of the derived class.If a class is inherited using a protected access specifier than both the public and protected members of the base class become the protected. members of the derived class.
However, the sub-class members can determine the values of the base class private members by using the Base class public member functions.
class A { int a; public: int value() { a=10; return a; } }; class B:public A { public: int b; void bvalue() { b=value(); //now b is assigned a value 10 .This is how the sub class can determine the value of the base class private member printf("%d",b); variables } }; int main() { B o; o.bvalue(); return 1; }
Dynamic Binding can be used to access the members of the derived class using the Base class pointer.Dynamic binding or late-binding or run time binding is achieved using virtual functions in the Base class.If the Base class pointer pointing to the derived class object and the matching function is declared virtual in base class, then which function is call is decided at run-time using virtual table entry.
Friendly Functions
Like send method in Ruby,C++ allow the Friend Functions which are not within the scope of the class to access the private members of the class. The friend function are defined like any other function without using either the keyword friend or :: scope resolution operator.Since they are not within the scope of the class ,they cannot be called using the objects of the class.Declaration of a friend function in either the public or private part of the class does not change it functionality.
Friend Classes
A class declared as a friend class of an another class can access all the private and protected members of the class extending friendship.
Access Control in Java
Access control can be defined as the methods that limit accessibility of the resources to a set of users or programs to enforce integrity, confidentiality or availability constraints. Java provides two levels of access controls
- "Top Level" – Public, or Package-Private (no explicit modifier, also known as default).
- "Member Level" – Public, Private, Protected or Package-Private (no explicit modifier, also known as default).
Top Level
On the Top level come classes and interfaces. An Interface can only be declared as public. While a class can be declared to be either public or default. If a class is declared as public then it is visible to all the classes in the same or a different package. But if a class is declared with no access specifier i.e. default, then it is public in its own package i.e. it cannot be accessed outside the package other than the one in which it is declared.
Member Level
At the member level we can declare fields, methods and constructors as public, private, protected and default. Public and default modifiers are used in the same way as the top level and with the same meaning. When a member of a class is declared as private then it can be accessed only within the class. Also, when a member is declared as protected then it can be accessed by all the classes in the same package and the sub classes (of its class) in other packages.
Final Keyword
When this keyword is used along with the class declaration, the class cannot be inherited by any other class.If a method is declared to be final then that method cannot be overridden and if a variable is declared as final then its value cannot be changed.
Example
To understand it in more detail consider the following the example.
In the example each package contains two classes. Class C is a sub class of class A. Assuming class A as public then its members can be accessed like – Class A – It can access all its members independent of their access modifier. Class B – It can access all the members of class A except those are private. Class C – It can access public and protected members of class A because it is a sub class of class A. Class D – It can access only the public members of class A. The access modifiers of the top level component govern whether its members are available in the other packages i.e. even if we are having public methods in a class but the class is declared as default then its methods will not be available in other packages. If one’s class is going to be used by other coders then he must ensure that errors due to misuse do not happen. For this he must provide the most restrictive access to its members like always declare the fields as private and provide methods to access/modify them.
package package1; public class Parent { /** * */ private int privateVariable; public int publicVariable; protected int protectedVariable; int defaultVariable; private int getPrivateVariable() { return privateVariable; } private void setPrivateVariable(int privateVariable) { this.privateVariable = privateVariable; } public int getPublicVariable() { return publicVariable; } public void setPublicVariable(int publicVariable) { this.publicVariable = publicVariable; } protected int getProtectedVariable() { return protectedVariable; } protected void setProtectedVariable(int protectedVariable) { this.protectedVariable = protectedVariable; } int getDefaultVariable() { return defaultVariable; } void setDefaultVariable(int defaultVariable) { this.defaultVariable = defaultVariable; } public static void main(String[] args) { // TODO Auto-generated method stub Parent parent=new Parent(); parent.setDefaultVariable(5); parent.setPrivateVariable(4); parent.setProtectedVariable(6); parent.setPublicVariable(9); } } package package1; public class ChildInSamePackage extends Parent{ /** * Public, Protected and Default members available. */ public static void main(String[] args) { // TODO Auto-generated method stub ChildInSamePackage childInSamePackage = new ChildInSamePackage(); childInSamePackage.setDefaultVariable(1); childInSamePackage.setProtectedVariable(5); childInSamePackage.setPublicVariable(7); //childInSamePackage.setPrivateVariable(7); // not allowed. Compile time Error Parent parent =new Parent(); parent.setDefaultVariable(0); parent.setProtectedVariable(1); parent.setPublicVariable(0); //parent.setPrivateVariable(0); //not allowed. compile time error } } package package1; public class ClassInSamePackage { /** * Public, Protected and Default available but only to parent class object. */ public static void main(String[] args) { // TODO Auto-generated method stub Parent parent = new Parent(); parent.setDefaultVariable(0); parent.setProtectedVariable(5); parent.setPublicVariable(9); //parent.setPrivateVariable(9); //not allowed } } package package2; import package1.Parent; public class ChildInDifferentPackage extends Parent{ /** * Both public and Protected members can be accessed. * But Protected can be accessed only through inheritance. */ public static void main(String[] args) { // TODO Auto-generated method stub ChildInDifferentPackage childInDifferentPackage = new ChildInDifferentPackage(); childInDifferentPackage.setProtectedVariable(5); childInDifferentPackage.setPublicVariable(4); Parent parent = new Parent(); parent.setPublicVariable(7); //parent.setProtectedVariable(7); // not allowed. protected members are available only through inheritance. } } package package2; import package1.Parent; public class ClassInDifferentPackage { /** * Only public members of parent class can be accessed * but using the object of parent class. */ public static void main(String[] args) { Parent parent = new Parent(); parent.setPublicVariable(4); // only public members are available. } }
Access Control in C#
The accessibility levels of the types (class, interface, struct, enum etc.) and the members, controls whether they can be used from the other code in our assembly (*) or other assemblies.
Accessibility levels provided by C#
- "Public": It can be used for the types and type members. It allows them to be accessed everywhere in the same assembly or the other assembly.
- "Private": It can be used only for the members. Private members are accessible only within the class or the struct in which they are declared.
- "Protected": It is a member access modifier. It allows the class to hide its members from the other classes except the child classes.
- "Internal": It can be used both for the types and type members. Internal types and members are accessible only by the code in the same assembly.
- "Protected Internal": It’s a combination of protected and internal modifier. It allows the types and the members to be used by any code in the same assembly or by any derived class in another assembly. A protected internal element can be accessed in a derived class in another assembly by using an instance of the derived class.
Usage of these access modifiers for all types or members is dependent on the conditions like the accessibility of the container restricts the accessibility of a type member.
- - Assembly is a physical unit that can be executed, deployed, versioned and secured.
internal class InternalClass { private int privateMember1; protected int protectedMember2; internal int internalMember3; protected internal int protectedInternalMember4; private class NestedClass { void Test(Class1 foo) { foo.Member1 = 0; //OK foo.Member2 = 0; //OK foo.Member3 = 0; //OK foo.Member4 = 0; //OK } } } public class PublicClass { private void Method1() { } private int privateMember1; protected int Member1 { get { return privateMember1; } set { Method1(); privateMember1 = value; } } internal int internalMember2; public int publicMember3; protected internal int protectedInternalMember4; } class Test { void Test1() { InternalClass internalClass = new InternalClass(); //OK internalClass.privateMember1 = 0; //Compilation error here internalClass.protectedMember2 = 0; //Compilation error here internalClass.internalMember3 = 0; //OK internalClass.protectedInternalMember4 = 0; //OK } } internal class DerivedClass : InternalClass { private void Test2() { privateMember1 = 0; //Compilation error here protectedMember2 = 0; //OK internalMember3 = 0; //OK protectedInternalMember4 = 0; //OK } private class NestedClass { void Test(DerivedClass foo) { foo.privateMember1 = 0; //Compilation error here foo.protectedMember2 = 0; //OK foo.internalMember3 = 0; //OK foo.protectedInternalMember4 = 0; //OK } void Test(Class1 foo) { foo.privateMember1 = 0; //Compilation error here foo.protectedMember2 = 0; //Compilation error here foo.internalMember3 = 0; //OK foo.protectedInternalMember4 = 0; //OK } } } ------------------ Class in a different assembly ------------------------------- public class Test { void Test1() { InternalClass internalClass = new InternalClass(); //Compilation error here PublicClass publicClass = new PublicClass; //OK publicClass.Method1(); //Compilation error here publicClass.privateMember1 = 0; //Compilation error here publicClass.Member1 = 0; //Compilation error here publicClass.internalMember2 = 0; //Compilation error here publicClass.publicMember3 = 0; //OK publicClass.protectedInternalMember4 = 0; //Compilation error here } } internal class DerivedClass : PublicClass { private void Test2() { Member1 = 0; //OK internalMember2 = 0; //Compilation error here publicMember3 = 0; //OK protectedInternalMember4 = 0; //OK } private class NestedClass { void Test(DerivedClass foo) { foo.Member1 = 0; //Compilation error here foo.internalMember2 = 0; //Compilation error here foo.publicMember3 = 0; //OK foo.protectedInternalMember4 = 0; //OK } void Test(Class2 foo) { foo.Member1 = 0; //Compilation error here foo.internalMember2 = 0; //Compilation error here foo.publicMember3 = 0; //OK foo.protectedInternalMember4 = 0; //Compilation error here } } }
Conclusion
The philosophies of access controls in object oriented languages have not changed much over time but certainly the access control across different Object Oriented Languages are different if not completely.
Thus we can see that by using the access modifier's each OO language controls the access to its class members.
References
- http://ruby-doc.org/core/
- http://rubylearning.com/satishtalim/ruby_access_control.html
- http://phrogz.net/programmingruby/tut_classes.html
- http://msdn.microsoft.com/en-us/library/kktasw36(v=VS.80).aspx
- http://www.kuzbass.ru:8086/docs/isocpp/access.html
- http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8a.doc%2Flanguage%2Fref%2Fcplr130.htm
- http://download.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html
- http://msdn.microsoft.com/en-us/library/wxh6fsc7.aspx
- http://stackoverflow.com/questions/2084801/c-using-declaration-scope-and-access-control
- http://en.wikipedia.org/wiki/Class_(computer_programming)#Member_accessibility
- http://www.jvoegele.com/software/langcomp.html
- http://csharp.net-informations.com/language/csharp-access-specifiers.htm
- http://blogs.oberon.ch/tamberg/2007-10-30/understanding-csharp-access-modifiers.html
- http://www.enscand.com/howtos/access/access.html