CSC/ECE 517 Fall 2012/ch1 1w34 vd

From Expertiza_Wiki
Jump to navigation Jump to search

Introduction

Object oriented languages support inheritance through different mechanisms. Methods from parent classes can be re-implemented in child classes to improve the behavior of the child class without having to re-write the whole class or define a completely new method. As method re-implementation in descendant classes is achieved differently in different classes it is crucial to understand these mechanisms.

Re- implantation of methods in PHP 5

The object model in PHP 5 was rewritten to include OO features such as final, abstract and visibility for classes and methods and improve the overall performance of the language. Re-implantation of methods in PHP 5 can be achieved in the following manner:

Object Inheritance

This is an important OO feature that PHP uses in its object model. When a subclass extends from a parent class, it inherits all the public and protected methods from the parent class. The issues that affect how the inherited methods behave are:

Method Visibility

All methods that are defined as ‘public’ and ‘protected’ in the parent class are ‘visible’ in the subclass. Public and protected are access modifiers that define the visibility of methods between different classes. Methods defined as ‘private’ access are not visible in the subclass. Methods declared without any access keyword are ‘public’.
Example:

<?php

class GameClass
{


public function_construct(){ } //Declare a public constructor


public function GamePublic(){ } //Declare a public method
protected function GameProtected(){ } //Declare a protected method
private function GamePrivate(){ } //Declare a private method

function Play() //This is public
{ 
$this->GamePublic(); $this->GameProtected(); $this->GamePrivate();
 } } ?> $mygame = new GameClass;
$mygame->GamePublic(); // Works
$mygame->GameProtected(); // Fatal Error
$mygame->GamePrivate(); // Fatal Error
$mygame->Play(); // Public, Protected and Private work




class BoardGame extends GameClass
 {
//This is public

function PlayDice()
{

$this->GamePublic();

$this->GameProtected();

$this->GamePrivate(); // Fatal Error

 }

}

$myboard = new BoardGame;
$myboard->GamePublic(); // Works

$myboard->PlayDice(); // Public and Protected work, not Private


Overriding

If a subclass defines a new method with the same name and signature as that of the method from the parent class then an object of the subclass calling that method will execute the implementation of the method defined in the subclass. Example: change this example of overriding

<?php
class game
{
public function game-name($string)
 {
 echo 'Game: ' . $string . PHP_EOL;
 }
 
public function play()
 {
 echo 'I like this game.' . PHP_EOL;
 }
}
class chess-game extends game
{
 public function game-name($string)
 {
 echo 'Board Game: ' . $string . PHP_EOL;
 }
}
$gm = new game ();
$cg = new chess-game();
$game->game-name('cricket'); // Output: 'Game: cricket'
$gm->play();       // Output: 'I like this game' 
$cg->game-name('chess'); // Output: 'Board Game: chess'
$cg->play();       // Output: 'I like this game'
?>

Scope Resolution

When a subclass extends a class, then the overridden and overloaded methods of the parent class can be called, using the scope resolution operator (::) inside the subclass.

<?php
class ParentClass
{
protected function parentFunc()
 {
 echo "ParentClass::parentFunc()\n";
 }
}
class ChildClass extends ParentClass
{
// Override parent's definition
public function parentFunc()
 {
 // Call the parent function
 parent::parentFunc();
 echo "ChildClass::parentFunc()\n";
 }
}
$class = new ChildClass();
$class->parentFunc();
?>
Output
ParentClass::parentFunc()
ChildClass::parentFunc()

Class Abstraction

Abstract methods in PHP 5 are methods inside abstract class that only provide signature for the method without any actual implementation to it. An abstract method has an abstract keyword at the beginning of the method declaration. A class containing even a single abstract method should be declared as abstract by adding the abstract keyword to its declaration. Any class inheriting from an abstract class should provide implementation of all of the abstract methods or declare it abstract. No class can inherit from more than one abstract class. The inheriting class, should have the same signature for the inherited abstract methods and the same or less restrictive visibility as defined in the methods in the abstract class.

<?php
abstract class ParentAbstractClass
{
 // Method without definition
 abstract protected function getName();
 abstract protected function setName($name);
 // Method with definition
 public function printName()
 {
  print $this->getName() . "\n";
 }
}
class ConcreteChild extends ParentAbstractClass
{
 //Method from abstract class implemeted
 protected function getName() 
 {
  return "ConcreteChild";
 }
 //Method from abstract class implemeted
 public function setName($name) 
 {
  return "ConcreteChild : {$name}";
 }
}
class ConcreteChild2 extends ParentAbstractClass
{
//Method from abstract class implemeted
 public function getname() 
 {
  return "ConcreteChild2";
 }
//Method from abstract class implemeted
 public function setName($name) 
 {
  return "ConcreteChild2 : {$name}";
 }
}
$class1 = new ConcreteChild;
$class1->printName();
echo $class1->setName('FOO') ."\n";
$class2 = new ConcreteChild2;
$class2->printName();
echo $class2->setName('FOO') ."\n";
?>
The above example will output:
ConcreteChild
ConcreteChild : FOO
ConcreteChild2
ConcreteChild2 : FOO

Object Interfaces

Interface in PHP is a mechanism that specifies methods that a class requires to implement, without having to provide any implementation to these methods inside the interface. An interface is declared like any other class, just that it is prefixed by the interface keyword and none of its methods have any content to them. A class providing implementation of the methods of an interface has the implements keyword followed by the class name for that class. Similarly, an interface can be inherited by another interface so that, a class implementing the interface that is lowest in the inheritance hierarchy gets to implement the methods from all the interfaces. Methods inside the interface being implemented by a class should have the same signature as that of the interface. Note: An interface cannot be instantiated.

<?php
interface food
{
//Interface method with no implementation
 public function eat();
}

interface fruit { //Interface method with no implementation public function fruitName(); }
interface Apple extends food, fruit { //Interface method with no implementation public function juice(); }
class GreenApple implements Apple { //Implementing methods from all the interfaces public function eat() { echo “Food: eat()”; } public function fruitName() { echo “Fruit: fruitName()”; } public function juice() { echo “Apple: juice()”; } } ?>

The class GreenApple will implement all the methods that it has inherited from all the interfaces in inheritance hierarchy.


Objective-C

In Objective-C the method declaration is done in the ‘@interface’ section and the method definitions are provided in the ‘@implementation’ section and these two are stored in different files. There are two types of methods in Objective C –
1.Instance Methods: Instance methods are denoted by placing a (-) sign before them while declaring them and are used to access and modify the instance variables over a particular instance of a class.

2.Class Methods: Class Methods do not require an object of the Class to be created in order to be called upon. These are very similar to ‘Static’ methods in JAVA. They are denoted by putting a (+) sign before the method name while declaring them.

For example:

myPizza = [Pizza new];	//new is a Class method on Pizza Class 
[mypizza setcost]	//setcost is an instance method called on the particular instance ‘mypizza’

Method Overriding

Objective-C does not support multiple inheritance and method overloading. However it supports single inheritance and methods can be overridden to re-implement the instance methods in subclasses.

Example: Patient.h class

//Interface for Superclass. Here we declare methods and variables
@interface Patient: NSObject /*NSObject is the root object and Patient inherits from NSObject*/ { int patient_number; //attributes of patient class char sex; } @property int patient_number, char sex; -(int) return_patient_number; -(char) return_sex; /*method declarations for superclass specifying the return type and arguments*/ -(void) setDetails: (int)number : (char)s; @end

Patient.m class

//Implemetation for Superclass. Here we define methods to modify instance variables
#import “Patient.h” //importing interface class @implementation Patient @synthesize patient_number, sex; //synthesizing instance variables -(void) setDetails : (int)number : (char)s //method definitions { patient_number=number; sex=s; } -(int) return_patient_number { return patient_number } -(char)return_sex { return sex } @end

Now we define a new class that inherits Patient Class
Diabetic.h

//interface for the subclass. Here we declare methods for the subclass
#import “Patient.h” //importing Superclass’s interface @interface Diabetic : Patient { int blood_sugar; //additional attribute for the subclass } @property int blood_sugar; -(void) setDetails: (int)number : (char)s : (int)sugar; //method declarations -(int) return_blood_sugar; @end

Diabetic.m

//implementation for the subclass
#import “Diabetic.h” //Subclass importing its own interface @implementation Diabetic: Patient @synthesize blood_sugar; -(void) setDetails: (int)number : (char)s : (int)sugar //Method Overriding { patient_number=number; sex=s; blood_sugar=sugar; } -(int) return_blood_sugar { return blood_sugar; } @end
//Test program to run the code
# import “Diabetic.h” int main( int argc, char *argv[]) { NSAutoreleasepool *pool = [[NSAutoreleasePool alloc] init]; Diabetic *dia=[[Diabetic alloc] init]; [dia setDetails: 10 :’M’ :500]; NSLog( @”Patient number is %i ,Patient Sex is %c, Patient sugar level is %i”, [dia return_patient_number], [dia return_sex ],[dia return_blood_sugar]); [dia release]; return 0; }

Output would be: Patient number is 10 ,Patient Sex is M, Patient sugar level is 100

Abstract Classes

Abstract Classes are provided to the users to give them a common interface to interact with the objects. There is no access specifier for abstract classes in Objective-C. Users cannot generate pure abstract classes. However a number of abstract classes have been provided to the users. For Example: NSObject in the above example is an abstract class. It cannot be instantiated by the user but is the root class of every class in Objective C.

Protocols

A protocol is similar to Interfaces in JAVA. It specifies a set of behavior/methods that the object who conforms to that protocol must implement. A protocol is defined by using a @protocol directive before the name of the protocol. For example:

@protocol Alive
 {
  : (void) sleep;
  : (void) eat; 
 }
@end

If a Class Human conforms to this protocol then it must implement both the methods in it’s implementation section. However it need not declare these methods.

@ interface Human: NSObject <Alive>
 {
 }
@end

#import “Human.h” @implementation Human -(void) sleep { NSLog(@”I Sleep”); } -(void) eat { NSLog(@”I Eat”); } @end

Categories

Categories provide a mechanism to enhance the functionality of a class without subclassing it. You can add new methods to an existing class and also utilize the methods in the existing class by the use of categories. For example:

@interface Alive: NSObject
 {
  : (void) sleep;
  : (void) eat; 
 }
@end

#import ”Alive.h” @interface Alive(OnLiquidDiet) {  : (void) sleep;  : (void) drinks; } @end

Here we have defined a new Category ‘OnLiquidDiet’ for the Alive Class which has a different method ‘drinks’ other than the ‘sleep’ method in the Alive Class. Although categories can be used for overriding methods, it is not recommended because you cannot access the original method definition once it is overridden in a category. In the above example if we override the ‘sleep’ method in the ‘OnLiquidDiet’ category we won’t be able to access the original ‘sleep’ method from the category.

Re-implementation of Methods in Python

Methods can be re-implemented using inheritance in Python, but unlike Objective-C it supports multiple inheritance. However it does not support method overloading. In order to implement inheritance the names of the super class separated by commas are defined in the class statement.The Object class is the default base class of all the classes in Python. A sample example to show re-implementation of method in the subclass is shown below:

class Patient(object):
 def  __init__(self,patient_number,age,weight):
  self.patient_number=patient_number
  self.age=age
  self.weight=weight
 def displayDetails(self):
  return “Patient’s name:” +str(self.patient_number)+ “Patient’s age”+str( self.age),+ “Patient’s weight”+str(self.weight)

Now we define another class that inherits from the Patient Class

Class Diabetic (Patient):
 def __init__(self,patient_ number,age,weight,blood_sugar):
  super.__init__(patient_ number,age,weight)
  self.blood_sugar=blood_sugar
 def displayDetails(self):
  return super. displayDetails(self)+” Blood Sugar:” + str(self.blood_sugar)

This example typically represents a single inheritance. The Diabetic class overrides the’ __init__’ and ‘displayDetails’ method and in each method a super method call is invoked in order to call the superclass method. If any of these methods were not defined in the subclass and a method call had been invoked on the object of the subclass for that method, then the superclass’s method would have been invoked.

Abstract Base Classes

An Abstract Base Class is similar to Interfaces in JAVA and complement duck typing in Python by defining that the class would conform to a given behavior. An abstract class cannot be instantiated and any class that registers to the abstract class must define the abstract methods of the abstract class, though it may choose not to re-implement the methods that had already been defined in the abstract class. The abc module is used for defining an abstract base class. An example to define an abstract class is shown below:

import abc
class PaintBuilding(object):
 __metaclass__= abc.ABCMeta
 @abc.abstractmethod
 def contour():
  pass
def color(): return ”Paint with Red and Blue”

A class needs to register with the Abstract Base Class in order to use it.

import abc
from packageA import PaintBuilding
Class PaintRectangularBuilding(object):
 def contour():
  return ”Building is Rectangular” 
 def color():
  return “Paint the Rectangular building Red and Blue”
PaintBuilding.register(PaintRectangularBuilding)

Multiple Inheritance

Since Multiple Inheritance is supported in Python, we can define several classes separated by commas in the class statement. For example:

Class Amphibian(LandAnimal,MarineAnimal):

Since multiple inheritance is prone to conflicts, there is something defined as the Method Resolution Order (MRO) that specifies the sequence in which the method or attribute is looked up in the various super classes. If there is no multiple inheritance then the lookup is done in left to right, depth first order when a particular method on the subclass object is called upon that is not defined in the subclass. However, this approach leads to the same parent being visited more than once if a diamond shaped hierarchy is obtained in case of multiple inheritance. To resolve the conflicts in such cases a new-style MRO has been defined that essentially considers only the rightmost occurrence of any super class and neglects the other occurrences. Use of Super keyword In Python 3 the super method can be used without any arguments, though the old version of it with arguments is also supported. In order to prevent the same method in the super class being looked up twice in case of diamond shaped hierarchy in multiple inheritance, the super method is used. For example:

Class ResponseTime():
 def __init__(self,time):
  self.time=time
Class RamResponseTime(ResponseTime): def __init__(self,time); print ”RAM ResponseTime” super().__init__ (self,time)
Class CacheResponseTime(ResponseTime): def __init__(self,time): print ”CacheResponseTime” super().__init__ (self,time)
Class RegisterResponseTime (RamResponseTime, CacheResponseTime) def __init__(self,time): print “RegisterResponseTime” super().__init__ (self,time)

If we had called the __init__ method on Class names instead of super method then the ResponseTime’s __init__ method would have been called twice. The use ofthe super keyword ensures that the super class’s method is called only one in case of multiple inheritance in diamond shaped graphs

Re- implantation of methods in Perl

Unlike many other OO languages, Perl does not have any special syntax for defining class. Instead, a class can be simply described as a package that acts as a namespace for variables and methods contained in that package. Since a package does not behave like a conventional class the methods inside the class may or may not expect an object or class reference as the first argument. Each class (or package as we said) contains a @ISA array. This array is required to store the package name (of type string) of all those classes that have been inherited by that class. Inheritance of methods in Perl is a built-in feature but in order to inherit attributes, explicit code needs to be written inside the class inheriting attributes from another class. So, when a class has been inherited by a subclass, all the methods from the parent’s package are implicitly available to the subclass.

package Fruit::Apple;
use parent 'Fruit'; # sets @Fruit::Apple::ISA = ('Fruit');
my $apple = Fruit::Apple->new( 'GreenApple', $data );
$apple->save();

The Fruit::Apple class doesn’t have a save() method defined in it. So Perl tries to find the save() method in the parent class for Fruit::Apple, that is the Fruit class. If the Fruit class also didn’t have the save() method, Perl dies. In this case, although the method save() of the Fruit class is being called, the object saved will be that of the fruit::Apple object.

Method Overriding

Within the subclass, we can override the methods of the parent class. When calling the method from an object reference of the subclass, the implementation inside the subclass will be executed. We can also execute the implementation of any parent class method inside the subclass using the Super keyword. With this keyword, any method from the parent class can be called inside the subclass but this does not hold for subroutine calls and class methods. SUPER is a pseudo class, so methods of the parent class cannot be called as the methods of the SUPER class.

SUPER::save($data); # FAIL: looks for save() sub in package SUPER
SUPER->save($data); # FAIL: looks for save() method in class # SUPER
$thing->SUPER::save(); # Okay: looks for save() method in parent# classes

Super Keyword

In a multi-level hierarchy, the super keyword is resolved not on the basis of the object’s class but on the basis of the package inside which it is being called. This allows classes in a multi-level hierarchy to call its immediate parent’s method using the super keyword. Example

package A;
sub new {
return bless {}, shift;
}
sub speak {
my $self = shift;
$self->SUPER::speak();
say 'A';
}
package B; use parent 'A'; sub speak { my $self = shift; $self->SUPER::speak(); say 'B'; }
package C; use parent 'B'; sub speak { my $self = shift; $self->SUPER::speak(); say 'C'; }

my $c = C->new();
$c->speak();

Output:
A //Method speak() from package A will complete execution first
B // Followed by the speak() method from package B
C //And lastly the method speak() from package C will finish execution

Multiple Inheritance

Though multiple inheritance is bound to raise design issues, nevertheless it provides a convenient mechanism for code reuse and implementation. Perl supports multiple inheritance with a complicated method lookup mechanism. When a class is inheriting multiple classes, then the names of all the classes will go inside the @ISA array. When resolving method names, Perl will search for the method in the following order and stops as soon as it finds an implementation: 1.Inside the class on which the method call has been made. 2.The first class in the @ISA array and if not found it will go up to the inheritance hierarchy for this class until it finds the method. 3.The second class in the @ISA array and if not found it will go up to the inheritance hierarchy for this class until it finds the method. 4.The third class in the @ISA array and so on… So Perl will lookup into the inheritance hierarchy of each of the classes in the @ISA array in a depth-first search from left to right manner. In doing so, it may happen, that a grand-parent class is visited before its child class as can be understood from the following diagram.

When calling a method on the Child class, it will be resolved in the order – Child, Parent 1, Granparent 1, Parent 2, Grandparent 2. This might be a problem as we are checking Grandparent 1 before checking all of its subclasses down the hierarchy. This problem can be solved by using the C3 resolution from the mro pragma. The c3 resolution order ensures that all the classes of a parent class are searched before the parent class itself. So the order of resolution will be – Child, Parent 1, Parent 2, Grandparent 1, Grandparent 2. The resolution is no more depth-first search now.

package Child;
use mro 'c3';
use parent 'Parent1', 'Parent2';

Conclusion

Methods are re implemented in inherited classes to provide custom implementation of methods in Derived Classes as well as to utilize some of the predefined functionalities in Super classes. This approach has been demonstrated in PHP, Objective-C, Python, Perl along with relevant examples and also some of the related mechanisms have been demonstrated. These examples show that method re-implementation is achieved differently in different OO languages.

References