CSC/ECE 517 Fall 2011/ch1 1i lj
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. This wiki article intends to explain the method implementation capabilities of Java, Ruby, and C++.
Overriding Methods
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. 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.
Java
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.
Method Overriding and Super
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. 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. 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. 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.
Overloading Methods
While not explicitly related to the distinction between methods in a subclass and a superclass, method overloading is another use of polymorphism in Java. The language is able to distinguish between methods in a class that have the same name but are implemented with different signatures inside of the same class. The actual method that is called will depend on which parameters are sent. The methods cannot have the same number and type of parameters, even if they have a different return type. One such overloaded method is the print() method in the java.io.PrintStream class[1]:
public void print(boolean b) public void print(char c) public void print(char[] s) public void print(float f) public void print(double d) public void print(int i) public void print(long l) public void print(Object obj) public void print(String s)
Abstract Methods and Classes
Ruby
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. 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 overridden 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:
irb(main):013:0* a=Parent.new => #<Parent:0x60db48> irb(main):014:0> a.methodLocation In Parent class => nil irb(main):015:0> a = Child.new => #<Child:0x2a020a0> irb(main):016:0> a.methodLocation In Child class => nil
Alias
Abstract Methods and Classes
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
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.
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