CSC10210 Topic 6 - Polymorphism and Interfa
CSC10210 Topic 6 - Polymorphism and Interfa
Topic 6
Polymorphism, abstract classes and interfaces
©
Southern Cross University
Copyright materials reproduced herein are used under the provisions of the
Copyright Amendment Act (1989).
Readings, if any, indicated in this work have been copied under section VB of the Copyright Amendment Act 1989
Copies, if any, were made by Southern Cross University in February, 2012
for private study only by students.
Contents
6-3
CSC10210 Study Guide Topic 6 -Polymorphism, abstract classes and interfaces
Objectives
On completion of this topic you should be able to:
1. Understand the role of the Object class.
2. Understand and use polymorphism in object-oriented systems.
3. Design and use abstract classes.
4. Use the sealed keyword.
5. Design and use interfaces.
Introduction
Polymorphism is one of the distinctive attributes of object-oriented programming languages. It adds
to the re-use provided by inheritance to allow the same code to be designed to process many different
(though related) objects. In this topic we will extend our knowledge of classes to see how
polymorphism works. We will also extend our basic knowledge of inheritance to the design of
abstract classes and interfaces which enhance polymorphism by providing special base classes to aid
us to produce polymorphic designs. We will start our discussion of polymorphism by studying the
system class Object and see how it may be used in a polymorphic way. We will then look as
abstract classes and interfaces which are language features specially designed to allow polymorphic
behavior.
6-4
CSC10210 Study Guide Topic 6 -Polymorphism, abstract classes and interfaces
6-5
CSC10210 Study Guide Topic 6 -Polymorphism, abstract classes and interfaces
if (p.Equals(p2))
Console.WriteLine("p and p2 are the same object");
if (p.Equals(p3))
Console.WriteLine("p and p3 are the same object");
When we execute this code only one line will be printed:
p and p3 are the same object
Make sure you understand why this is true. The diagrams introduced in Topic 2 may help you
understand this if you are not clear.
Although the inherited Equals() methods check that the objects being compared are the same object
in memory, this does not have to be the case. The Equals() method is also declared as virtual so
that classes may redefine it to compare objects in other ways. For example, the above Person class
above could redefine the Equals methods to compare name strings, which would mean that two
objects could be considered equal even if they represented different objects in memory. An example
coding for the above Person class would be as follows:
public override bool Equals(Object obj)
{
if (obj == null || GetType() != obj.GetType()) return false;
Person p = (Person)obj;
return (name == p.GetName());
}
This implementation is slightly complicated because the Equals() member function has an Object
parameter. We need to check that the parameter is actually a Person object before we check if the
name strings are equal (otherwise they may not have a name string!). Also in this example, we used
the GetType() member function which we look at next.
The third member function of the Object class that you may find useful is the GetType() member
function which returns an object that represents the class type of the object. We will not go into
details about the object returned but you may find this method used in code you examine. In general
we will not be too concerned about the object returned, we just will want to compare for equality so
that we can see if two objects have the same type as was done in the code above.
The following activity will let you see the other methods of the Object class. You will see that they
are interrelated to a certain extent.
Activity 6-1:
Read Section 11.7 of textbook (pp. 434–435).
1. In the example program above using the Person class, explain why the line:
Console.Writeline(p);
prints a line when p is not a string.
2. Suppose we implement the following code segment using the Person class above.
Person p1 = new Person(“Jo”);
Person p2 = new Person(“Jo”);
if (p1.Equals(p2))
Console.WriteLine(“p1 and p2 are equal”);
Explain why p1 and p2 are not equal (message is not displayed) even though they have
the same argument “Jo” passed to the constructor.
6-6
CSC10210 Study Guide Topic 6 -Polymorphism, abstract classes and interfaces
Examine the full list of member functions of the Object class in the Visual C# documentation:
http://msdn.microsoft.com/en-us/library/system.object_members.aspx
3. Explain in your own words how the GetHashCode() function is related to the
Equals() function.
4. Explain in your own words what the MemberwiseClone() member function does and
how you think it could be used.
5. Explain in your own words the relationship between Equals() and
ReferenceEquals() member functions.
Now that we have introduced the Object class we will use it to show how polymorphism works.
Polymorphism
In this section we will discuss the idea of polymorphism in object-oriented languages and how it
increases code re-use. We will do this by examining an example method that illustrates the concept.
Polymorphism is about using methods of a base class to process objects of a class derived from the
base class. Remember that objects of derived classes inherit methods and attributes, can redefine
them, but cannot remove them so they will always be present in objects of derived classes. Carefully
look at the following method definition.
public void PrintString(Object o)
{
Console.WriteLine(o);
}
This method will happily take a reference to any program object as an argument! C# allows variables
(a parameter variable in this case) declared with a particular class to hold references to any object of
derived classes. This makes sense because all objects of derived classes will also have inherited all of
the base class fields and members. Now, since the Object class is the base class of all class
hierarchies, this particular method will be able to take any object reference as a parameter. That in
turn implies that the WriteLine(o) function call will always be able to call the ToString()
member function inherited from the Object class for any object passed as parameter.
Suppose we have a simple class called Person defined as follows.
class Person
{
private readonly string name;
public Person(string n)
{
name = n;
}
6-7
CSC10210 Study Guide Topic 6 -Polymorphism, abstract classes and interfaces
Person
-name: string
+Person(n: string)
+GetName(): string
Student StaffMember
Printname(p);
Printname(s1);
Printname(st1);
Notice how we have used one implementation of a method to print any of the three object types. This
is re-using the Printname() member function for several different objects, which happen to have a
common inheritance ancestor.
You may have already noticed that a potential problem exists here. What if the method called in the
base class is redefined in the derived class. For example, what if the Student class in the above
example redefined the GetName() method, which is perfectly legal in C# if the method is declared
virtual in the base class. We would then have a version of the method in both the base class and
the derived class. The answer is that C# performs dynamic binding. This means that the language
decides which method is appropriate at run-time so if the Student class did redefine the GetName()
method then its version of the GetName() method would be called.
Activity 6-2:
Read Section 12.1 to 12.3 in the Textbook (pp. 442-444). This reading also gives an
introduction to the rest of this topic. Try to answer the following:
1. In the example above, suppose we defined the above Printname() function as follows:
6-8
CSC10210 Study Guide Topic 6 -Polymorphism, abstract classes and interfaces
Next we see how the idea of polymorphism results in further extensions to the syntax of class
declaration, specifically abstract classes.
Abstract classes
The idea of polymorphism is so important to object-oriented program design that the language is
extended to allow better use of these facilities in large projects. In this section we will discuss abstract
classes which are classes designed to be base classes only, and never instantiated. In the next section
we will look at interfaces which take the idea one step further.
We can declare a class abstract which usually means that it contains abstract methods. A class with
abstract methods must be declared abstract. For example, suppose we have a class hierarchy for 2-
dimensionsal shapes. We will require each shape to return its area but we will not know in advanced
how each shape will describe itself. We can declare an abstract class Shape to make sure all derived
classes can return their area as follows.
abstract class Shape
{
private double x, y;
public Shape(double x, double y)
{
this.x = x;
this.y = y;
}
6-9
CSC10210 Study Guide Topic 6 -Polymorphism, abstract classes and interfaces
Console.WriteLine("Area is {0}",s.Area());
}
There is a final aspect to abstract classes. We have not shown how properties may be declared
abstract. This is achieved in a similar way to methods. For example, we could add an abstract
property for colour (represented by an int type) to our Shape class with the following definition.
public abstract int colour
{
get;
set;
}
Notice how this definition again uses the semicolon in place of a block of code to perform the get and
set actions. As before, this means the property has a default implementation, however the abstract
keyword means that the body must be defined in all derived classes.
UML also has a special notation for abstract classes. The abstract class name is presented in italic
font, everything else appears similar to concrete classes. It is easy to miss the italics in many
diagrams so beware. Figure 6.2 shows the UML class diagram for the Shape/Square/Rectangle
relationship.
Shape
-x: double
-y: double
+Shape(x, y: double)
+Area(): double
Square Rectangle
-side: double -side1: double
-side2: double
+Square(s: double)
+Rectangle(s1: double, s2: double)
Activity 6-3:
Read Section 12.4 – 12.5.5 in the textbook (pp. 448 - 459). This reading contains a quite
complicated example, much closer to a real-life program than the simple examples we use in the
study guide.
1. Develop and test a definition for a class for a Rectangle shape (see Figure 6.2).
2. Develop and test code for using the above PrintArea() function to print the area for
a square object and a rectangle object. You will need to declare example objects
before calling the function.
Abstract classes are design to be used as base classes for other classes. What if we do not want a class
to be used as a base class? C# provides a keyword for this that we will examine next.
6-10
CSC10210 Study Guide Topic 6 -Polymorphism, abstract classes and interfaces
Activity 6-4:
Read Section 12.6 in the Textbook (p. 466). Explain in your own words how the following
would be a valid declarations for a class designer:
public override sealed void DoSomething() {…}
The final section for this topic will look at interfaces which are a pure version of an abstract class that
has no implementation details at all.
Interfaces
An interface can be considered an abstract class with no methods implemented. It is not declared as a
class however, it is considered a separate structure called an interface. It also provides an additional
attribute useful for object-oriented design. A class can implement more than one interface. Although
it was not explicitly stated, a class can only be derived from one base class. However, a class can
implement as many interfaces as the programmer desires. This directly follows from the lack of
method implementation in an interface as there can be no confusion which method to execute at
runtime.
We will introduce interfaces with a very simple example. The following IPrintable interface is to
provide a single member function to print the object details.
public interface IPrintable
{
void Print(); // print object details
}
6-11
CSC10210 Study Guide Topic 6 -Polymorphism, abstract classes and interfaces
Notice the interface keyword is used where the class keyword appears in class definitions. You
should also take note that, since it is an interface, the keywords virtual or abstract are not
necessary in the method definitions since they are implied by the interface declaration. In addition,
individual methods cannot be declared public as this is an interfaces desired state and a syntax error
will be generated if you use an access specifier such as public.
To demonstrate use of this interface we will redefine the Student class from earlier in this topic. We
will extend the previous definition to implement the IPrintable interface as follows.
class Student : Person, IPrintable
{
// fields and methods as before
Person
<<interface>>
IPrintable -name: string
+Person(n: string)
+Print(): void +GetName(): string
Student StaffMember
6-12
CSC10210 Study Guide Topic 6 -Polymorphism, abstract classes and interfaces
Activity 6-5:
Read Section 12.7 in the Textbook (pp. 466-476). Note that this reading again uses a fairly
complex, though more real-world example. The actual code to do with interfaces forms a small
part of the overall example code.
1. What is the logical (non-syntax) difference between an abstract class and an interface?
Could you replace any interface with an abstract class?
2. Write down a definition of an interface for objects that can be incremented. It will need
one member function called Increment(). Then write down the definition of a class
that implements the interface. You will probably need some sort of number field in your
class.
3. Write down the definition of a function that would print an array of objects with the
IPrintable interface discussed above.
That will be enough class variations for designing very complex and complete class hierarchies. You
will come across all of these variations while using the .NET Framework Class Library, including
those you saw in the reading in Activity 6-5.
Topic Summary
This topic examined polymorphism and the C# support for it. We started by discussing the Object
class which is the root of all class inheritance hierarchies in C#. We used the Object class to show
how we can use polymorphism to write code to process all objects in a C# program. We then
demonstrated how we can use polymorphism to process our own class hierarchies, using a common
base class. Abstract classes were then introduced and we showed how these can be used for
polymorphic processing even though no objects can be instantiated using an abstract class. Finally,
we looked at interface structures which are purely abstract constructs in C#. Interfaces are a
description of method signatures which must be implemented in classes. Interfaces have the
additional attribute that a class may implement multiple interfaces, and so be processed by many
different code segments.
6-13
CSC10210 Study Guide Topic 6 -Polymorphism, abstract classes and interfaces
Answers to Activities
Activity 6-1:
1. The Person instance object p is automatically converted into a string by calling the ToString()
method of the object. Every object has one of these because it is a method inherited from the
Object class.
2. They are not equal because they are not the same object in memory. In this case the Equals()
method is inherited from the Object class and in that version of the method a check is made as to
whether the objects are the same object in memory. Note that the Equals() method could have
been redefined in the shown derived class Person to behave differently to the version inherited
from the Object class but was not in this case.
3. The GetHashCode() member function returns a unique identifier for each object in memory.
This means that two objects that return true with the Equals() function inherited from the
Object class will have the same hash code returned from the GetHashCode() function.
4. The MemberwiseClone() function copies the memory contents of one object to another. This
has a subtle effect when the object contains references to other objects. Supose we have the
following class definition:
class Person
{
private string name;
public Person(string n) { name = n; }
public string GetName() { return name;}
public Person GetCopy() { return (Person) MemberwiseClone(); }
}
And then suppose we execute the following code:
Person p1 = new Person("Barry");
Person p2 = p1.GetCopy();
The end result is that the two objects p1 and p2 end up with references to the same string object
as shown in the following diagram:
p1
"Barry"
p2
This is known as a shallow copy. A deep copy would have also created a new string object for
p2.
5. Both can compare if the two objects are the same two objects in memory. However, the
Equals() method may be overridden to have different behaviour, whereas the
ReferenceEquals() cannot so it always checks if the two object references given as
parameters are the same objects in memory.
Activity 6-2:
1. No. This is not permitted because polymorphism works with derived classes, not base classes.
The reason this cannot work is that the Student class may have methods and attributes that are
not defined in the Person base class, whereas in the reverse situation this is not possible.
2. No. Again, StaffMember is not derived from the Student class. Again, the reason this cannot
work is that the Student class may have methods and attributes that are not defined in the
StaffMember class. (StaffMember and Student are both derived from the same Person base
class).
6-14
CSC10210 Study Guide Topic 6 -Polymorphism, abstract classes and interfaces
Activity 6-3:
1. Here is a complete Rectangle class definition, including the constructor.
class Rectangle : Shape
{
private double side1;
private double side2;
PrintArea(s);
PrintArea(r);
}
}
Activity 6-4:
The reading briefly describes how this may be used. First, since we are using the override keyword
the method DoSomething() must be declared in a base class. Second, since we are now applying the
sealed keyword, in any derived classes this method may not be overridden. We are cutting off the
inheritance possibilities from this level of the inheritance hierarchy.
Activity 6-5:
1. There are two main differences between interfaces and abstract classes. The first is that an
interface cannot have any implementation for any of its methods. It is however also possible for
an abstract class to have no implementation for its methods. The second and distinct difference is
that we can inherit/implement more than one interface. A class can only ever use one class
(abstract or otherwise) as its base class.
So the answer to the second question is that you cannot replace an interface with an abstract class
because a derived class may want to use the interface and another class or interface to
respectively inherit or implement.
2. A possible interface definition is:
public interface IIncrementable
{
void Increment(); // increment the object
}
We can implement this interface in a class containing a number as in the following example:
public class Number implements IIncrementable
6-15
CSC10210 Study Guide Topic 6 -Polymorphism, abstract classes and interfaces
{
private int numb = 0;
6-16