CSC/ECE 517 Fall 2011/ch1 1i lj

From Expertiza_Wiki
Jump to navigation Jump to search

Reimplementation of Methods in Descendant Classes


Introduction

In object-oriented programming, a modified version of one class can be derived from an existing class and it will inherit all of the fields and methods from the existing class. This concept is known as subclassing or implementation inheritance. The derived class (also called extended, descendant, child, or subclasses) will automatically inherit all of the fields and methods from the superclass (also called ancenstor, parent, or base classes). Once a subclass is created, the methods and fields of the superclass can be used or replaced by methods and fields in the subclass if desired. The various object-oriented programming languages have different capabilities when it comes to inheritance and method reimplementation. One typical use for implementation inheritance is to extend or modify the capabilities an existing class so as to add or slightly change its functionality, which is known as “specialization.” This can allow a subclass to use most of the features of a superclass, but modify the behavior somewhat to get a desired output without the need to duplicate coding.This wiki article intends to explain the method implementation capabilities of Java, Ruby, and C++.

Method overriding, in object oriented programming, is a language feature that allows a subclass to provide a specific implementation of a method that is already provided by one of its superclasses[1]. The reimplementation of the method in the subclass overrides (replaces) the implementation in the superclass. It is generally still possible to refer to the superclass version of the method - even within the subclass version of the method - if needed.

Abstract classes and methods are another way to use implementation inheritance in object-oriented programming. An abstract class is a class that contains at least one abstract method, and an abstract method is a method that has no implementation. Abstract classes and methods cannot be instantiated directly, but are intended to be made concrete in subclasses, where the abstract methods are implemented. Such classes are generally meant to serve as a template for other classes to use, and can be used to represent specialized behavior and help to keep code organized in a hierarchy of classes. Any class that has a single abstract method in it is considered to be an abstract class, but a class consisting of only abstract methods is considered an interface. An interface does not allow any methods to be fully implemented inside of it.

Java

The Java programming language was first developed by Sun Microsystems, with the first version released in 1995. It is an object-oriented and class-based language that takes advantage of polymorphism.

Inheritance in Java

In Java, each class can only inherit directly from a single superclass, which is referred to as single inheritance. Additional subclasses can be created from existing subclasses, however. A descendant class is created using the extends keyword. Each class is implicitly a subclass of the Object class in Java, and Object has no super class. A Java subclass receives all of the members (fields, methods, and classes) of the superclass, but not the constructors (because constructors are not members).

Method Overriding and Super

In Java, a method in the subclass is said to “override” a superclass method when the subclass version has the same signature (name, parameters, and return type) as the superclass version[2]. The subclass version of the overridden method (called an “instance method”) will only be executed when an object of the subclass type calls that method. Any other calls to the method from objects of the superclass type will use the superclass version of the method. The example below shows the distinction between an overridden version of a method in a subclass versus the original method in the superclass. The superclass is Sport and has the class method, and the Subclass is Basketball, which has the instance method. In this example, Basketball extends Subclass.

The super keyword can be used in an instance of the subclass to call back to the the overridden version of the method in the superclass, instead of using the overriding instance method in the subclass[3]. Furthermore, super must be used in the subclass if it is using a parameterized method from the superclass.

public class Sport {
    public static void exampleClassMethod() {
        System.out.println("Class method in Sport superclass.");
    }
    public void testInstanceMethod() {
        System.out.println("Instance method in Sport.");
    }
}

public class Basketball extends Sport {
    public static void exampleClassMethod() {
        System.out.println("The class method in Basketball.");
    }
    public void testInstanceMethod() {
	super.testInstanceMethod();   //call to the superclass method
        System.out.println("The instance method in Basketball.");
    }

    public static void main(String[] args) {
        Basketball myBasketball = new Basketball();
        Sport mySport = myBasketball;
        Sport.exampleClassMethod();
        mySport.testInstanceMethod();
	}
}

The output of this code is:

Class method in Sport superclass.
Instance method in Sport.
Instance method in Basketball.

Abstract Methods and Classes

A subclass tends to be a specialized version of a superclass. Furthermore, superclasses can be concrete (meaning instance objects can be created from them), or abstract (objects cannot be directly created from them). Abstract classes are useful when a set of basic methods for a class and its subclasses need to be defined, but the actual implementation and specialization of these methods can be done in subclasses. By definition in Java, if a method within a class has been defined as abstract, the class must be declared abstract as well. The abstract methods have no body, but are used to establish an access modifier. In Java, the abstract keyword is used to declare a method or class to be considered abstract. Below is an example of an abstract parent class called Automobile, with a non-abstract child class called SportsCar:

Creation of the abstract class Automobile:

public abstract class Automobile
{
     public String make;   //make of the vehicle
     public abstract void vehicleType();  //abstract vehicle 
}

Creation of the non-abstract subclass SportsCar:

public class SportsCar extends Automobile 
{
     public SportsCar(String m) {
          make = m;
     }

     public void vehicleType() {
     System.out.println("The " + make + "is a Sports Car");
     }
}

Testing the program:

public class Main
{
     public static void main( String[] args )
     {
          SportsCar ferrari = new SportsCar("Ferrari");
          ferrari.vehicleType();
     }
}

The output is:

The Ferrari is a Sports Car

Ruby

Ruby is a dynamically-typed, object-oriented language that was developed in the mid 1990's by Yukihio Matsumoto.

Inheritance in Ruby

In Ruby, a class can only have one direct superclass, so it is considered a single inheritance language. However, Ruby's classes can access the functionality of mixins, as a sort of simulated multiple inheritance. Mixins allow a class to implement methods from different modules, if the module has defined instance methods[4]. Another feature of Ruby is that, if a method is called in a subclass that is not defined in the direct parent class, Ruby will continue to look upwards through the hierarchy of superclasses until the method is found. One example of this is the to string (to_s) method in Ruby. A subclass is created using the < notation: Subclass < Superclass.

Method Overriding

In Ruby, an instance method of a class is reimplemented by extending the class and redefining the method, as show below:

class Parent  
  def methodLocation  
    puts 'In Parent class'  
  end  
  end  
      
class Child < Parent  
  def methodLocation  
    puts 'In Child class'  
  end  
end  

a=Parent.new
a.methodLocation
a = Child.new  
a.methodLocation

The output of this code is:

In Parent class
In Child class

C++

Basic overriding method in pure C++

In native C++, a derived class function having the same name and parameters as a base class virtual function will *always* override it. In C++/CLI you have the option of using the new contextual keyword to specify whether you want to override a base class function or hide it. Example:

ref class Base
{
public:
    virtual void Goo()
    {
        Show("Base::Goo");
    }
    
    virtual void Boo()
    {
        Show("Base::Boo");
    }
    
    virtual void Doo()
    {
        Show("Base::Doo");
    }
};

ref class Derived : Base
{
public:
    //Overrides Base::Goo

    virtual void Goo()
    {
        Show("Derived::Goo");
    }
    
    //Overrides Base::Boo as above

    virtual void Boo() = Base::Boo
    {
        Show("Derived::Boo");
    }
    
    //Hides Base::Doo

    virtual void Doo() new
    {
        Show("Derived::Doo");
    }
};

Here's some sample code that invokes the above methods on a Base handle referencing a Derived object.

void _tmain()
{
    Base^ r = gcnew Derived();
    r->Goo();
    r->Boo();
    r->Doo();
}


You'll get the following output :

Derived::Goo
Derived::Boo
Base::Doo

C++/CLI

When Microsoft brought out the Managed Extensions to C++ with VS.NET 7, C++ programmers accepted it with mixed reactions. While most people were happy that they could continue using C++, nearly everyone was unhappy with the ugly and twisted syntax offered by Managed C++. Microsoft obviously took the feedback it got very seriously and they decided that the MC++ syntax wasn't going to be much of a success.

On October 6th 2003, the ECMA announced the creation of a new task group to oversee development of a standard set of language extensions to create a binding between the ISO standard C++ programming language and Common Language Infrastructure (CLI). It was also made known that this new set of language extensions will be known as the C++/CLI standard, which will be supported by the VC++ compiler starting with the Whidbey release (VS.NET 2005).

Renamed Overriding in C++/CLI

Native C++ insisted that the derived class method name must match the name of the base class virtual method that it is overriding. C++/CLI allows us to have a derived class method override a base class virtual method even if the derived class method name does not match the base class method name. Of course the method signatures must be equivalent. The following code snippet should make things clear.

ref class Base
{
public:
    virtual void Goo()
    {
        Show("Base::Goo");
    }

    virtual void Boo()
    {
        Show("Base::Boo");
    }    
};

ref class Derived : Base
{
public:
    //Overrides Base::Goo

    virtual void Goo()
    {
        Show("Derived::Goo");
    }

    //Overrides Base::Boo

    virtual void Woo() = Base::Boo
    {
        Show("Derived::Woo");
    }

    //New function Boo in Derived

    virtual void Boo() new
    {
        Show("Derived::Boo");
    }
};

Some code that invokes these methods :

void _tmain()
{
    Base^ r = gcnew Derived();
    r->Goo();
    r->Boo();    
    
    Derived^ d = dynamic_cast<Derived^>(r);
    d->Goo();
    d->Boo();
    d->Woo();
}

The output will be :

Derived::Goo
Derived::Woo
Derived::Goo
Derived::Boo
Derived::Woo

Multiple overriding

In native C++, a function of a class that inherits from multiple base classes/interfaces, can override more than one base class function only if all the base classes/interfaces have a function of the same name and signature. C++/CLI lets you specify which method overrides which base/ class/interface method, provided the function signatures match.

The following code snippet demonstrates multiple overriding :

interface class INish
{
    void Goo();
};

interface class IBuster
{
    void Boo();
    void Moo();
};

ref class Base
{
public:
    virtual void Goo() 
    {
        Show("Base::Goo");
    }

    virtual void Boo()
    {
        Show("Base::Boo");
    }    
};

ref class Derived : Base, INish, IBuster
{
public:    
    //Overrides both Base::Goo, INish::Goo, IBuster::Moo

    virtual void Goo() = Base::Goo, INish::Goo, IBuster::Moo
    {
        Show("Derived::Goo");
    }

    //Overrides Base::Boo

    virtual void Boo() = Base::Boo
    {
        Show("Derived::Boo");
    }

    //Override IBuster::Boo

    virtual void Hoo()= IBuster::Boo
    {
        Show("Derived::Hoo");
    }    
};

Use the below code snippet to invoke these methods :


void _tmain()
{
    Base^ r = gcnew Derived();
    r->Goo();
    r->Boo();    

    INish^ i = dynamic_cast<INish^>(r);
    i->Goo();
    

    IBuster^ b = dynamic_cast<IBuster^>(r);
    b->Boo();
    b->Moo();
}

The output will be :

Derived::Goo
Derived::Boo
Derived::Goo
Derived::Hoo
Derived::Goo

C#

Introduction for overriding method

An override method provides a new implementation of a member inherited from a base class. The method overridden by an override declaration is known as the overridden base method. The overridden base method must have the same signature as the override method. You cannot override a non-virtual or static method. The overridden base method must be virtual, abstract, or override. An override declaration cannot change the accessibility of the virtual method. Both the override method and the virtual method must have the same access level modifier. You cannot use the following modifiers to modify an override method: 1. new 2. static 3. virtual 4. abstract

An overriding property declaration must specify the exact same access modifier, type, and name as the inherited property, and the overridden property must be virtual, abstract, or override.

When an instance method declaration includes an override modifier, the method is said to be an override method. An override method overrides an inherited virtual method with the same signature. Whereas a virtual method declaration introduces a new method, an override method declaration specializes an existing inherited virtual method by providing a new implementation of that method.

The method overridden by an override declaration is known as the overridden base method. For an override method declared in a class C, the overridden base method is determined by examining each base class of C, starting with the direct base class of C and continuing with each successive direct base class, until an accessible method with the same signature as is located. For the purposes of locating the overridden base method, a method is considered accessible if it is public, if it is protected, if it is protected internal, or if it is internal and declared in the same program as C.

A compile-time error occurs unless all of the following are true for an override declaration:

  • The overridden base method is a virtual, abstract, or override method. In other words, the overridden base method cannot be static or non-virtual.
  • The overridden base method is not a sealed method.
  • The override declaration and the overridden base method have the same return type.
  • The override declaration and the overridden base method have the same declared accessibility. In other words, an override declaration cannot change the accessibility of the virtual method.

Example

In this example, there is a base class, Square, and a derived class, Cube. Because the area of a cube is the sum of the areas of six squares, it is possible to calculate it by calling the Area() method on the base class.

// cs_override_keyword.cs
// Calling overriden methods from the base class
using System;
class TestClass 
{
   public class Square 
   {
      public double x;

      // Constructor:
      public Square(double x) 
      {
         this.x = x;
      }

      public virtual double Area() 
      {
         return x*x; 
      }
   }

   class Cube: Square 
   {
      // Constructor:
      public Cube(double x): base(x) 
      {
      }

      // Calling the Area base method:
      public override double Area() 
      {
         return (6*(base.Area())); 
      }
   }

   public static void Main()
   {
      double x = 5.2;
      Square s = new Square(x);
      Square c = new Cube(x);
      Console.WriteLine("Area of Square = {0:F2}", s.Area());
      Console.WriteLine("Area of Cube = {0:F2}", c.Area());
   }
}

The result is:

Area of Square = 27.04
Area of Cube = 162.24

Conclusion

In object-oriented programming, the most important feature is inheritance of descendant classes from parent classes. The inheritance of members and methods are convenient for the users to implement. But sometimes, we want to improve the methods of descendant classes. The overriding method is a basic method for reimplementation of descendant classes for basic class, abstract class or virtual class. Here we describe the definition and procedure of several languages Ruby, Java, C++/CLI and C#. It is worth to notice the differences between these languages in reimplentation of methods for descendant classes.

References