Home

Polymorphism and Abstraction

 

Characteristics of Inheritance

 

Namespaces and Inheritance

Imagine you had created a class named Person in a namespace named People as follows:

Source File: Persons.cs
using System;

namespace People
{
    public class Person
    {
	private string _name;
	private string _gdr;

	public Person()
	{
	    this._name = "Not Available";
	    this._gdr  = "Unknown";
	}

	public Person(string name, string gender)
	{
	    this._name = name;
	    this._gdr  = gender;
	}

	private string FullName
	{
	    get { return _name; }
	    set { _name = value; }
	}

	private string Gender
	{
	    get { return _gdr; }
	    set { _gdr = value; }
	}
    }
}

 

If you decide to derive a class from it, remember that this class belongs to a namespace. To inherit from this class, the compiler will need to know the namespace in which the class was created. Class inheritance that involves namespaces relies on qualification, like the calling of the members of a namespace. To derive a class from a class member of a namespace, type the name of the namespace, followed by the period operator ".", and followed by the name of the base namespace. Here is an example:

Source File: StaffMembers.cs
using System;

namespace HighSchool
{
	public class Teacher : People.Person
	{
		private string _pos;

		public Teacher()
		{
			this._pos = "Staff Member";
		}

		public Teacher(string pos)
		{
			this._pos     = pos;
		}

		private string Position
		{
			get { return _pos; }
			set { _pos = value; }
		}
	}
}

If you need to call the class that was defined in a different namespace, remember to qualify its name with the period operator. Here is an example:

Source File: Exercise.cs
using System;

class Exercise
{
    public static int Main()
    {
	People.Person man = new People.Person("Hermine Sandt", "Male");
	HighSchool.Teacher staff = new HighSchool.Teacher("Vice Principal");

	Console.WriteLine();
	return 0;
    }
}

Alternatively, to use the contents of a namespace, prior to calling a member of that namespace, you can type the using keyword followed by the name of the namespace. Here is an example:

Source File: Exercise.cs
using System;
using People;
using HighSchool;

class Exercise
{
    public static int Main()
    {
	Person man = new Person("Hermine Sandt", "Male");
	Teacher staff = new Teacher("Vice Principal");

	Console.WriteLine();
	return 0;
    }
}
 

Practical Learning Practical Learning: Using Inheritance With Namespaces

  1. Start Microsoft Visual C# and create a Console Application named Geometry2
  2. To create a new class, on the main menu, click Project -> Add Class...
  3. Set the Name to Square and press Enter
  4. Change the file as follows:
     
    using System;
    
    namespace Geometry2
    {
        public class Square
        {
            private double _side;
    
            public Square()
            {
                _side = 0.00;
            }
    
            public Square(double s)
            {
                _side = s;
            }
        }
    }
  5. To create a new class, on the main menu, click Project -> Add Class...
  6. Set the Name to Rectangle and press Enter
  7. Change the file as follows:
     
    using System;
    
    namespace Geometry2
    {
        public class Rectangle
        {
            double _length;
            double _height;
    
            public Rectangle()
            {
                _length = 0.00;
                _height = 0.00;
            }
    
            public Rectangle(double L, double H)
            {
                _length = L;
                _height = H;
            }
        }
    }
  8. Save all

Protected Members

To maintain a privileged relationship with its children, a parent class can make a member available only to classes derived from it. With this relationship, some members of a parent class have a protected access level. Of course, as the class creator, it is your job to specify this relationship.

To create a member that derived classes only can access, type the protected keyword to its left. Here are examples:

Source File: Persons.cs
using System;

public class Person
{
	private string _name;
	private string _gdr;

	public Person()
	{
		this._name = "Not Available";
		this._gdr    = "Unknown";
	}
	public Person(string name, string gender)
	{
		this._name = name;
		this._gdr  = gender;
	}

	protected string FullName
	{
		get { return _name; }
		set { _name = value; }
	}

	protected string Gender
	{
		get { return _gdr; }
		set { _gdr = value; }
	}
		
	public void Show()
	{
		Console.WriteLine("Full Name: {0}", this.FullName);
		Console.WriteLine("Gender:    {0}", this.Gender);
	}
}

You can access protected members only in derived classes. Therefore, if you instantiate a class outside, you can call only public members:
Source File: Exercise.cs
using System;

class Exercise
{
    public static int Main()
    {
	People.Person man = new People.Person("Hermine Sandt", "Male");

	Console.WriteLine("Staff Member");
	man.Show();

	Console.WriteLine();
	return 0;
    }
}

This would produce:

Staff Member
Full Name: Hermine Sandt
Gender:     Male

If you create a class member and mark it as protected, the classes derived of its parent class, created in the current program or outside the current program, can access it. If you want the member to be accessed only by derived classes implemented in the same program but not derived classes implemented outside of the current program, mark the member as protected internal. Here are examples:

Source File: Persons.cs
using System;

public class Person
{
	private string _name;
	private string _gdr;

	public Person()
	{
		this._name = "Not Available";
		this._gdr    = "Unknown";
	}
	public Person(string name, string gender)
	{
		this._name = name;
		this._gdr  = gender;
	}

	protected internal string FullName
	{
		get { return _name; }
		set { _name = value; }
	}

	protected internal string Gender
	{
		get { return _gdr; }
		set { _gdr = value; }
	}
		
	public void Show()
	{
		Console.WriteLine("Full Name: {0}", this.FullName);
		Console.WriteLine("Gender:    {0}", this.Gender);
	}
}

Virtual Members

We have just mentioned that you can create a new version of a member in a derived class for a member that already exists in the parent class. After doing this, when you call that member in your program, you need to make sure that the right member gets called, the member in the base class or the equivalent member in the derived class.

When you create a base class, if you anticipate that a certain property or method would need to be redefined in the derived class, you can indicate this to the compiler. On the other hand, while creating your classes, if you find out that you are customizing a property or a method that already exists in the base class, you should let the compiler know that you are providing a new version. In both cases, the common member should be created as virtual.

To create a virtual member, in the base class, type the virtual keyword to the left of the property or method. Based on this, the Area property of our Circle class can be created as follows:

class Circle
{
	public virtual double Area
	{
		get
		{
			return Radius * Radius * 3.14159;
		}
	}
}

In Microsoft Visual C#, unlike C++, if you omit the virtual keyword, the (Microsoft Visual C#) compiler would display a warning.

When you derive a class from an abstract class, since the methods (if any) of the abstract class were not implemented, you must implement each one of them in the derived class. When customizing virtual members in a derived class, to indicate that a member is already virtual in the base class and that you are defining a new version, type the override keyword to the left of its declaration. For example, the Area property in our Sphere class can be created as follows:

class Sphere : Circle
{
    public override double Area
    {
	get
	{
	    return 4 * Radius * Radius * 3.14159;
	}
    }

    public double Volume
    {
	get
	{
	    return 4 * 3.14159 * Radius * Radius * Radius;
	}
    }
}

In the same way, when implementing an abstract method of a class, type the override keyword to its left.

Practical Learning Practical Learning: Using Virtual Members

  1. To create a new class, on the main menu, click Project -> Add Class...
  2. Set the Name to a ShapeDescription and press Enter
  3. Change the file as follows:
     
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace Geometry2
    {
        public class ShapeDescription
        {
            public virtual string Description()
            {
                string Msg = "A quadrilateral is a geometric figure " +
                             "that has four sides and four angles.";
                return Msg;
            }
        }
    }
  4. Save the file as Quadrilaterals.cs in the Shapes1 folder
  5. Access the Square.cs file and override the Description method as follows:
     
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace Geometry2
    {
        public class Square : ShapeDescription
        {
            private double _side;
    
            public Square()
            {
                _side = 0.00;
            }
    
            public Square(double s)
            {
                _side = s;
            }
    
            public override string Description()
            {
                // Get the introduction from the parent
                string Introduction = base.Description() +
                       "\nA square is a quadrilateral that has four " +
                       "equal sides and four right angles";
    
                return Introduction;
            }
        }
    }
  6. Access Rectangle.cs file and change it as follows:
     
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace Geometry2
    {
        public class Rectangle : ShapeDescription
        {
            double _length;
            double _height;
    
            public Rectangle()
            {
                _length = 0.00;
                _height = 0.00;
            }
    
            public Rectangle(double L, double H)
            {
                _length = L;
                _height = H;
            }
    
            public override string Description()
            {
    
                // Get the introduction from the parent
                string Introduction = base.Description();
    
                string Msg = Introduction +
                        "\nA rectangle is a quadrilateral that has adjacent " +
            "perpendicular sides. This implies that its four " +
                             "angles are right.";
                return Msg;
            }
        }
    }
  7. Access the Program.cs file and change it as follows:
     
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    class Exercise
    {
        static void DisplaySquare(Square S)
        {
    	Console.WriteLine("Square Characteristics");
    	Console.WriteLine("Description: {0}", S.Description());
        }
    
        static void DisplayRectangle(Rectangle R)
        {
    	Console.WriteLine("Rectangle Characteristics");
    	Console.WriteLine("Description: {0}", R.Description());
        }
    
        static void Main()
        {
    	Square Sq = new Square();
    	Rectangle Rect = new Rectangle();
    
    	Console.WriteLine("========================================");
    	DisplaySquare(Sq);
    	Console.WriteLine("========================================");
    	DisplayRectangle(Rect);
    	Console.WriteLine("========================================");
    		
    	Console.WriteLine();
        }
    }
  8. Execute the project. This would produce:
     
    ========================================
    Square Characteristics
    Description: A quadrilateral is a geometric figure that has four 
    sides and four angles. A square is a quadrilateral that has four equal 
    sides and four right angles
    ========================================
    Rectangle Characteristics
    Description: A quadrilateral is a geometric figure that has four 
    sides and four angles.
    A rectangle is a quadrilateral that has adjacent perpendicular sides. 
    This implies that its four angles are right.
    ========================================
  9. Close the DOS window

Abstract Classes

In a program, you can create a class whose role is only meant to provide fundamental characteristics for other classes. This type of class cannot be used to declare a variable. Such a class is referred to as abstract. Therefore, an abstract class can be created only to serve as a parent class for other classes.

To create an abstract class, type the abstract keyword to the left of its name. Here is an example:

abstract class Ball
{
	protected int TypeOfSport;
	protected string Dimensions;
}

Practical Learning Practical Learning: Creating an Abstract Class

  1. To create an abstract class, access the ShapeDescription.cs file and change it as follows:
     
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace Geometry2
    {
        public abstract class ShapeDescription
        {
            public virtual string Description()
            {
                string Msg = "A quadrilateral is a geometric figure " +
                             "that has four sides and four angles.";
                return Msg;
            }
        }
    }
  2. Save the file

Abstract Properties and Methods

When creating a class that would mainly be used as a base for future inheritance, you can create one or more properties and make them abstract. To do this, when creating the property, type the abstract keyword to its left. Because you would not define the property, you can simply type the get keyword and its semi-colon in the body of the property.

A method of a class also can be made abstract. An abstract method can be a member of only an abstract class. If you make a method abstract in a class, you must not implement the method. To create an abstract method, when creating its class, type the abstract keyword to the left of the method's name. End the declaration with a semi-colon and no body for the method since you cannot implement it. Here is an example:

public abstract class Ball
{
    protected int TypeOfSport;
    protected string Dimensions;

    public abstract CalculateArea();
}

In the same way, you can create as many properties and methods as you see fit. You can choose what properties and methods to make abstract. This is important for inheritance.

Practical Learning Practical Learning: Creating an Abstract Property

  1. To create an abstract property, access the ShapeDescription.cs file and change its class as follows:
     
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace Geometry2
    {
        public abstract class ShapeDescription
        {
            public abstract string Name { get; }
    
            public virtual string Description()
            {
                string Msg = "A quadrilateral is a geometric figure " +
                             "that has four sides and four angles.";
                return Msg;
            }
        }
    }
  2. Access the Square.cs file and change it as follows:
     
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace Geometry2
    {
        public class Square : ShapeDescription
        {
            private double _side;
    
            public Square()
            {
                _side = 0.00;
            }
    
            public Square(double s)
            {
                _side = s;
            }
    
            public override string Name
            {
                get { return "Square"; }
            }
    
            public override string Description()
            {
                // Get the introduction from the parent
                string Introduction = base.Description() +
                "\nA square is a quadrilateral that has four " +
                              "equal sides and four right angles";
    
    
                return Introduction;
            }
        }
    }
  3. Access the Rectangle.cs file and change it as follows:
     
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace Geometry2
    {
        public class Rectangle : ShapeDescription
        {
            double _length;
            double _height;
    
            public Rectangle()
            {
                _length = 0.00;
                _height = 0.00;
            }
    
            public Rectangle(double L, double H)
            {
                _length = L;
                _height = H;
            }
    
            public override string Name
            {
                get { return "Rectangle"; }
            }
    
            public override string Description()
            {
    
                // Get the introduction from the parent
                string Introduction = base.Description();
    
                string Msg = Introduction +
                         "\nA rectangle is a quadrilateral that has adjacent " +
            "perpendicular sides. This implies that its four " +
                             "angles are right.";
                return Msg;
            }
        }
    }
  4. Access the Program.cs file and change it as follows:
     
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace Geometry2
    {
        public class Program
        {
            static void DisplaySquare(Square S)
            {
                Console.WriteLine("Square Characteristics");
                Console.WriteLine("Name:        {0}", S.Name);
                Console.WriteLine("Description: {0}", S.Description());
            }
    
            static void DisplayRectangle(Rectangle R)
            {
                Console.WriteLine("Rectangle Characteristics");
                Console.WriteLine("Name:        {0}", R.Name);
                Console.WriteLine("Description: {0}", R.Description());
            }
    
            static void Main()
            {
                FlatShapes.Square Sq = new FlatShapes.Square();
                FlatShapes.Rectangle Rect = new FlatShapes.Rectangle();
    
                Console.WriteLine("========================================");
                DisplaySquare(Sq);
                Console.WriteLine("========================================");
                DisplayRectangle(Rect);
                Console.WriteLine("========================================");
    
                Console.WriteLine();
            }
        }
    }
  5. Execute the project. This would produce:
     
    ========================================
    Square Characteristics
    Name:        Square
    Description: A quadrilateral is a geometric figure that has four 
    sides and four angles. A square is a quadrilateral that has four equal 
    sides and four right angles
    ========================================
    Rectangle Characteristics
    Name:        Rectangle
    Description: A quadrilateral is a geometric figure that has four sides 
    and four angles.
    A rectangle is a quadrilateral that has adjacent perpendicular sides. 
    This implies that its four angles are right.
    ========================================
  6. Close the DOS window

Sealed Classes

Any of the classes we have used so far in our lessons can be inherited from. If you create a certain class and don't want anybody to derive another class from it, you can mark it as sealed. In other words, a sealed class is one that cannot serve as base for another class.

To mark a class as sealed, type the sealed keyword to the left of the class keyword. Here is an example:

public sealed class Ball
{
	public int TypeOfSport;
	public string Dimensions;
}

There is not much to do about a sealed class. Simply remember that no class can be derived from it.

 

 

Interfaces

 

Introduction

Imagine you start creating a class and, while implementing or testing it, you find out that this particular class can be used instead as a general base that other classes can be derived from. An interface is a special class whose purpose is to serve as a template that actual classes can be based on. An interface is primarily created like a class: it has a name, a body and can have members.

To create an interface, instead of the class keyword, you use the interface keyword. By convention, the name of an interface starts with I. Here is an example:

interface ICourtDimensions
{
}

Practical Learning Practical Learning: Introducing Interfaces

  1. On the main menu, click Project -> Add New Item...
  2. In the Templates list, click Interface
  3. Set the Name to Quadrilateral and click Add
  4. Change the file as follows:
     
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace Geometry2
    {
        interface IQuadrilateral
        {
        }
    }
  5. Save the file

The Members of an Interface

As done for a class, the members of an interface are listed in its body. In an interface, you cannot declare fields like those we have used in other classes. Instead, if you want some type of member variable, you can create a property. If you create a property in an interface, you cannot define that property. One of the rules of an interface is that you cannot define any of its members. This is also valid for its properties. Therefore, if you create a property in an interface:

  • You can indicate that it would be read-only by adding an empty getter property to it. Here is an example:
     
    public interface ICourtDimensions
    {
    	double Length { get; }
    }
  • You can indicate that it would be write-only by adding an empty setter property to it. Here is an example:
     
    public interface ICourtDimensions
    {
    	double Length { set; }
    }
  • You can indicate that it would be used to write values to it and to read values from it. To provide this information, add a getter and a setter accessories to it. Here is an example:
     
    public interface ICourtDimensions
    {
    	double Length { get; set; }
    }

In the same way, you can create as many properties as you judge necessary in an interface. Besides the properties, an interface can also have other types of members such as methods. Here is an example of an interface that has one read-only property named NameOfSport, one read/write property named NumberOfPlayers, and one method named SportCharacteristics:

public interface IBall
{
	int NumberOfPlayers
	{
		get;
		set;
	}

	string NameOfSport
	{
		get;
	}

	void SportCharacteristics();
}

Practical Learning Practical Learning: Creating Members of an Interface

  1. To create a property, change the file as follows:
     
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace Geometry2
    {
        interface IQuadrilateral
        {
            double Area { get; }
        }
    }
  2. Save the file

An Interface as a Base Class

An interface is used to lay a foundation for other classes. For this reason, it is the prime candidate for class derivation. To derive from an interface, use the same technique we have applied in inheritance so far. Here is an example of a class named SportBall that derives from an interface named ISportType:

public class SportBall : ISportType
{
    int players;
    string sport;
}

Just as you can derive a class from an interface, you can create an interface that itself is based on another interface. Here is an example:

public interface ISportType : IBall
{
    SportCategory Type
    {
	get;
    }
}

The C# language doesn't allow multiple inheritance, which is the ability to create a class based on more than one class. Multiple inheritance is allowed only if the bases are interfaces. To create multiple inheritance, separate the names of interface, with a comma. Here is an example:

public interface ISportType : IBall, ICourtDimensions
{
	SportCategory Type
	{
		get;
	}
}

You can also involve a class as parent in a multiple inheritance scenario but there must be only one class. Here is an example in which a class called Sports derives from one class and various interfaces:

public interface Sports: Player, IBall, ICourtDimensions
{
}

Practical Learning Practical Learning: Inheriting From an Interface

  1. On the main menu, click Project -> Add New Item...
  2. In the Templates list, click Interface
  3. Set the Name to RightAngle and click Add
  4. Change the file as follows:
     
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace Geometry2
    {
        interface IRightAngle : IQuadrilateral
        {
            double Base { get; set; }
            double Height { get; set; }
            double Perimeter { get; }
        }
    }
  5. Access the Square.cs file and change it as follows:
     
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace Geometry2
    {
        public class Square : ShapeDescription, IRightAngle
        {
            . . .
        }
    }
  6. Access the Rectangle.cs file and change it as follows:
     
    using System;
    
    namespace Geometry2
    {
        public class Rectangle : ShapeDescription, IRightAngle
        {
            . . .
        }
    }
  7. Save all

Implementation of Derived Classes of an Interface

After creating an interface, you can derive other interfaces or other classes from it. If you are deriving other interfaces from an interface, you can just proceed as you see fit. For example, you can add or not add one or more new properties, you can add or not add one or more methods, etc. Here is an example:

Source File: Preparation.cs
public enum SportCategory
{
	SinglePlayer,
	Collective,
	Unknown
}

public interface ICourtDimensions
{
	double Length { get; set; }
	double Width  { get; set; }
}

public interface IBall
{
	int NumberOfPlayers
	{
		get;
		set;
	}

	string NameOfSport
	{
		get;
	}

	void SportCharacteristics();
}

public interface ISportType : IBall, ICourtDimensions
{
	SportCategory Type
	{
		get;
	}
}

If you derive a class, from an interface, you must implement all properties that were created in the interface. This means that you must define them so that, when a variable is declared of that class, the properties have meaning. In the same way, if you create a class that is based on an interface, you must implement all methods that were declared in the interface. If you derive a class from an interface that itself was derived from another interface, in your class, you must define all properties that were created in the whole parental lineage and you must implement all methods that were created in the parent and grant-parent interfaces. Here is an example:

Source File: Sport.cs
using System;

public class SportBall : ISportType
{
	int players;
	string sport;
	SportCategory _type;
	double Len;
	double Wdt;
    
	public SportBall(int nbr, SportCategory tp, string name)
	{
		players = nbr;
		_type   = tp;
		sport   = name;
	}

	public int NumberOfPlayers
	{
		get	{ return players;}
		set	{ players = value;}
	}

	public string NameOfSport
	{
		get	{ return sport; }
	}

	public SportCategory Type
	{
		get	{ return _type; }
	}

	public double Length
	{
		get { return Len; }
		set { Len = value; }
	}

	public double Width
	{
		get { return Wdt; }
		set { Wdt = value; }
	}

	public void SportCharacteristics()
	{
		Console.WriteLine("Sport Characteristics");
		Console.WriteLine("Name of Sport: {0}", NameOfSport);
		Console.WriteLine("Type of Sport: {0}", Type);
		Console.WriteLine("# of Players:  {0}", NumberOfPlayers);
		Console.WriteLine("Court Dimensions: {0}m x {1}m", Len, Wdt);
	}
}

Once the class is ready, you can then use it as you see fit. Here is an example:

Source File: Exercise.cs
using System;

class Exercise
{
    public static int Main()
    {
	SportBall volley = new SportBall(6,
					 SportCategory.Collective,
					 "Volley Ball");
	volley.Length = 18;
	volley.Width  = 9;
	volley.SportCharacteristics();

	Console.WriteLine();

	SportBall tennis = new SportBall(1,
					 SportCategory.SinglePlayer,
					 "Table Tennis");
	tennis.Length = 23.7;
	tennis.Width  = 8.25;
	tennis.SportCharacteristics();

	Console.WriteLine();
	return 0;
    }
}

This would produce:

Sport Characteristics
Name of Sport: Volley Ball
Type of Sport: Collective
# of Players:  6
Court Dimensions: 18m x 9m

Sport Characteristics
Name of Sport: Table Tennis
Type of Sport: SinglePlayer
# of Players:  1
Court Dimensions: 23.7m x 8.25m

Practical Learning Practical Learning: Implementing Derived Members of an Interface

  1. Access the Square.cs file and change it as follows:
     
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace Geometry2
    {
        public class Square : ShapeDescription, IRightAngle
        {
            private double _side;
    
            public Square()
            {
                _side = 0.00;
            }
    
            public Square(double s)
            {
                _side = s;
            }
    
            public override string Name
            {
                get { return "Square"; }
            }
    
            public override string Description()
            {
                // Get the introduction from the parent
                string Introduction = base.Description() + " " +
                    "A square is a quadrilateral that has four " +
                      "equal sides and four right angles";
    
                return Introduction;
            }
    
            public double Base
            {
                get { return (_side < 0) ? 0.00 : _side; }
                set { _side = value; }
            }
    
            public double Height
            {
                get { return (_side < 0) ? 0.00 : _side; }
                set { _side = value; }
            }
    
            public double Area
            {
                get { return Base * Base; }
            }
    
            public double Perimeter
            {
                get { return Base * 4; }
            }
        }
    }
  2. Access the Rectangle.cs file and change it as follows:
     
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace Geometry2
    {
        public class Rectangle : ShapeDescription, IRightAngle
        {
            double _length;
            double _height;
    
            public Rectangle()
            {
                _length = 0.00;
                _height = 0.00;
            }
    
            public Rectangle(double L, double H)
            {
                _length = L;
                _height = H;
            }
    
            public override string Name
            {
                get { return "Rectangle"; }
            }
    
            public override string Description()
            {
                // Get the introduction from the parent
                string Introduction = base.Description();
    
                string Msg = Introduction + " " +
                      "\nA rectangle is a quadrilateral that has adjacent " +
                "perpendicular sides. This implies that its four " +
                             "angles are right.";
                return Msg;
            }
    
            public double Base
            {
                get { return _length; }
                set { _length = value; }
            }
    
            public double Height
            {
                get { return _height; }
                set { _height = value; }
            }
    
            public double Area
            {
                get{ return Base * Height; }
            }
    
            public double Perimeter
            {
                get { return 2 * (Base + Height); }
            }
        }
    }
  3. Access the Program.cs file and change it as follows:
     
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace Geometry2
    {
        public class Program
        {
            static Square CreateASquare()
            {
                double side;
    
                Console.Write("Enter the side of the square: ");
                side = double.Parse(Console.ReadLine());
    
                Square Sqr = new Square(side);
                return Sqr;
            }
    
            static void DisplaySquare(Square S)
            {
                Console.WriteLine("Square Characteristics");
                Console.WriteLine("Name:        {0}", S.Name);
                Console.WriteLine("Description: {0}", S.Description());
                Console.WriteLine("----------------------------");
                Console.WriteLine("Side:        {0}", S.Base);
                Console.WriteLine("Perimeter:   {0}", S.Perimeter);
                Console.WriteLine("Area:        {0}", S.Area);
            }
    
            static Rectangle CreateARectangle()
            {
                double Len, Hgt;
    
                Console.WriteLine("Enter the dimensions of the rectangle");
                Console.Write("Base:   ");
                Len = double.Parse(Console.ReadLine());
                Console.Write("Height: ");
                Hgt = double.Parse(Console.ReadLine());
    
                Rectangle Recto = new Rectangle(Len, Hgt);
                return Recto;
            }
    
            static void DisplayRectangle(Rectangle R)
            {
                Console.WriteLine("Rectangle Characteristics");
                Console.WriteLine("Name:        {0}", R.Name);
                Console.WriteLine("Description: {0}", R.Description());
                Console.WriteLine("----------------------------");
                Console.WriteLine("Base:        {0}", R.Base);
                Console.WriteLine("Height:      {0}", R.Height);
                Console.WriteLine("Perimeter:   {0}", R.Perimeter);
                Console.WriteLine("Area:        {0}", R.Area);
            }
    
            static int Main()
            {
                Square Sq = new Square();
                Rectangle Rect = new Rectangle();
    
                Sq = CreateASquare();
                Rect = CreateARectangle();
    
                Console.WriteLine("============================");
                DisplaySquare(Sq);
                Console.WriteLine("============================");
                DisplayRectangle(Rect);
                Console.WriteLine("============================");
    
                Console.WriteLine();
    	    return 0;
            }
        }
    }
  4. Execute the application and test it. Here is an example:
     
    Enter the side of the square: 44.16
    Enter the dimensions of the rectangle
    Base:   58.62
    Height: 36.06
    ============================
    Square Characteristics
    Name:        Square
    Description: A quadrilateral is a geometric figure that has 
    four sides and four angles. A square is a quadrilateral that 
    has four equal sides and four right angles
    ----------------------------
    Side:        44.16
    Perimeter:   176.64
    Area:        1950.1056
    ============================
    Rectangle Characteristics
    Name:        Rectangle
    Description: A quadrilateral is a geometric figure that has 
    four sides and four angles.
    A rectangle is a quadrilateral that has adjacent perpendicular 
    sides. This implies that its four angles are right.
    ----------------------------
    Base:        58.62
    Height:      36.06
    Perimeter:   189.36
    Area:        2113.8372
    ============================
    
    Press any key to continue . . .
  5. Close the DOS window

Class Partial Implementation

In all of the classes we have defined so far, we were using a single file to implement the class. In C#, you can create a class (the same class) in different files. This means that you can start a class in one file and continue it in another file or in other files. This is referred to as partial implementation.

Author Note

If you have programmed in C++ or C++/CLI, don't confuse its header and source files with C#'s partial implementation of classes. In C++ or C++/CLI, you can include the structure of a class with its member variables (called fields in C#) and the declaration of its methods. In C++, a header file has the extension .h. Here is an example of a C++/CLI header file:

Header File: Cylinder.h
#pragma once

using namespace System;

public ref class CCylinder
{
private:
    double rad;
    double hgt;

public:
    CCylinder(void);
    CCylinder(double radius, double height);

    property double Radius
    {
	double get() { return rad; }
	void set(double value) { rad = value; }
    }

    property double Height
    {
	double get() { return hgt; }
	void set(double value) { hgt = value; }
    }

    double Volume();
};

In C++, after creating a header file, you can create its associated source file. The source file has the extention .cpp. Here is an example of the source file corresponding to the above header file:

Source File: Cylinder.cpp
#include "Cylinder.h"

CCylinder::CCylinder(void)
    : rad(0.00), hgt(0.00)
{
}

CCylinder::CCylinder(double radius, double height)
    : rad(radius), hgt(height)
{
}

double CCylinder::Volume()
{
    return rad * rad * hgt * Math::PI;
}

The above class can be tested with the following:

Source File: Exercise.cpp
#include "Cylinder.h"

using namespace System;

CCylinder ^ Initialize()
{
    CCylinder ^ c = gcnew CCylinder(36.12, 18.84);
    return c;
}

const void Show(CCylinder ^ vol)
{
    Console::WriteLine(L"Radius: {0}", vol->Radius);
    Console::WriteLine(L"Height: {0}", vol->Height);
    Console::WriteLine(L"Volume: {0}", vol->Volume());
}

int main()
{
    CCylinder ^ cyl = Initialize();
    Show(cyl);

    return 0;
}

 

As we have seen so far, in C#, you cannot simply and only declare a method in a file for a forward (later) implementation, as it's done in C, C++, C++/CLI, and (Object) Pascal. In C#, to create a class in various classes, start the class in one file but precede the class keyword with partial. Here is an example of a file named first.cs that contains some (2) private fields and some (2) properties:

Source File: geometry1.cs
using System;

partial class Cylinder
{
    private double rad;
    private double hgt;

    public Cylinder(double radius, double height)
    {
        this.rad = radius;
        this.hgt = height;
    }

    public double Radius
    {
        get { return rad; }
	    set { rad = value; }
    }

    public double Height
    {
	    get { return hgt; }
	    set { hgt = value; }
    }
}

After creating the class in one file, you can use as any of the classes as we have done so far. Here is an example:

Source File: Exercise.cs
using System;

class Program
{
    static Cylinder Initialize()
    {
        Cylinder c = new Cylinder(36.12, 18.84);
        return c;
    }

    static void Show(Cylinder vol)
    {
        Console.WriteLine("Radius: {0}", vol.Radius);
        Console.WriteLine("Height: {0}", vol.Height);
    }
   
    static int Main()
    {
        Cylinder cyl = Initialize();

        Show(cyl);

        Console.WriteLine();
        return 0;
    }
}

This would produce:

Radius: 36.12
Height: 18.84

Press any key to continue . . .

If you had created a partial class, or you got a partial class from somebody (not as part of a DLL or nor from another type of library), and you find out that the class is not complete, you can then complement it. One of the rules you must observe is that the partial class must have been marked as partial, as we did above. One of the advantages of partial implementation is that you don't have to get back to the first or previous file to modify it in order to complement the class. You can simply start another file and continue the class in it. Two other rules you must observe are that you must use the same name for the class and you must precede the class keyword with partial. Here is an example:

Source File: geometry2.cs
using System;

partial class Cylinder
{
    public Cylinder()
    {
        this.rad = 0.00;
        this.hgt = 0.00;
    }

    public double Volume()
    {
        return rad * rad * hgt * Math.PI;
    }
}

This class can then be tested as follows:

Source File: Exercise.cs
using System;

class Program
{
    static Cylinder Initialize()
    {
        Cylinder c = new Cylinder();
        
        c.Radius = 42.66;
        c.Height = 26.48;

        return c;
    }

    static void Show(Cylinder vol)
    {
        Console.WriteLine("Radius: {0}", vol.Radius);
        Console.WriteLine("Height: {0}", vol.Height);
        Console.WriteLine("Volume: {0}", vol.Volume());
    }
   
    static int Main()
    {
        Cylinder cyl = Initialize();

        Show(cyl);

        Console.WriteLine();
        return 0;
    }
}

This would produce:

Radius: 42.66
Height: 26.48
Volume: 151394.310951986

Press any key to continue . . .

Once a partial class has been created, you can create another based on it. The child class doesn't have to be partial, although it can be.

Practical Learning Practical Learning: Partially Implementing a Class

  1. Start Microsoft Visual C# and create a Console Application named Geometry3
  2. To add a new source file, on the main menu, click Project -> Add New Item...
  3. In the Templates list, click Code File
  4. Set the Name to circle1 and click Add
  5. Change the file as follows:
     
    public partial class Circle
    {
        private double _radius;
    
        public double Radius
        {
            get { return (this._radius <= 0) ? 0.00 : this._radius; }
            set { this._radius = value; }
        }
    
        public double Diameter
        {
            get { return this.Radius * 2; }
        }
    
        public double Circumference
        {
            get { return Diameter * 3.14159; }
        }
    
        public double Area
        {
            get { return this.Radius * this.Radius * 3.14159; }
        }
    }
  6. To create a new source file, in the Solution Explorer, right-click Geometry3 -> Add -> New Item...
  7. In the Templates list, make sure Code File is selected; otherwise, click it.
    Set the Name to circle2 and click Add
  8. Change the file as follows:
     
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    public partial class Circle
    {
        public Circle()
        {
            this.Radius = 0.00;
        }
    
        public Circle(double radius)
        {
            this.Radius = radius;
        }
    
        public void Present()
        {
            Console.WriteLine("Radius:        {0}", this.Radius);
            Console.WriteLine("Diameter:      {0}", this.Diameter);
            Console.WriteLine("Circumference: {0}", this.Circumference);
            Console.WriteLine("Area:          {0}", this.Area);
        }
    }
  9. To test the class, access the Program.cs file and change it as follows:
     
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace Geometry3
    {
        class Program
        {
            static Circle Initialize()
            {
                Console.Write("Enter the radius: ");
                double rad = double.Parse(Console.ReadLine());
                
                Circle c = new Circle(rad);
                return c;
            }
    
            static int Main()
            {
                Console.WriteLine(
    		"This application allows you to process a circle");
                Circle circ = Initialize();
    
                Console.WriteLine("\n==============================");
                Console.WriteLine("Circle Characteristics");
                Console.WriteLine("------------------------------");
                circ.Present();
                Console.WriteLine("==============================\n");
               
                return 0;
            }
        }
    }
  10. Execute the application to sew the result. Here is an example:
     
    This application allows you to process a circle
    Enter the radius: 10.08
    
    ==============================
    Circle Characteristics
    ------------------------------
    Radius:        10.08
    Diameter:      20.16
    Circumference: 63.3344544
    Area:          319.205650176
    ==============================
    
    Press any key to continue . . .
  11. Return to your programming environment
  12. To create a new source file, on the main menu, click Project -> Add New Item...
  13. In the Templates list, make sure Code File is selected; otherwise, click it.
    Set the Name to cylinder1 and press Enter
  14. Change the file as follows:
     
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    public partial class Cylinder : Circle
    {
        private double hgt;
    
        public double Height
        {
            get { return (this.hgt <= 0) ? 0.00 : this.hgt; }
            set { this.hgt = value; }
        }
    
        public double LateralArea
        {
            get { return this.Circumference * Height; }
        }
    
        public double TotalArea
        {
            get { return this.Area + this.LateralArea; }
        }
    
        public double Volume
        {
            get
            {
                return this.Radius * this.Radius * this.Height * Math.PI;
            }
        }
    }
  15. To create a new source file, in the Solution Explorer, right- click Geometry3 -> Add -> New Item...
  16. In the Templates list, make sure Code File is selected; otherwise, click it.
    Set the Name to cylindder2 and click Add
  17. Change the file as follows:
     
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    public partial class Cylinder : Circle 
    {
        // This is the default constructor of the cylinder
        // This constructor assumes that we don't have any dimension
        public Cylinder()
        {
            this.Radius = 0.00;
        }
    
        // This constructor assumes that there exists a radius
        // The radius could have been specified on a parent circle
        public Cylinder(double height)
        {
            this.Height = height;
        }
    
        // This constructor can be used to specify both
        // the radius of the base and the height of the volume
        // The radius can also have been defined by a parent circle
        public Cylinder(double radius, double height)
        {
            this.Radius = radius;
            this.Height = height;
        }
    
        new public void Present()
        {
            Console.WriteLine("Height:        {0}", this.Height);
            Console.WriteLine("Lateral Area:  {0}", this.LateralArea);
            Console.WriteLine("Total Area:    {0}", this.TotalArea);
            Console.WriteLine("Volume:        {0}", this.Volume);
        }
    }
  18. To test the class, access the Program.cs file and change it as follows:
     
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace Geometry3
    {
        class Program
        {
            static Circle Initialize()
            {
                Console.Write("Enter the radius: ");
                double rad = double.Parse(Console.ReadLine());
                
                Circle c = new Circle(rad);
                return c;
            }
    
            static double GetHeight()
            {
                Console.Write("Enter the height: ");
                double hgt = double.Parse(Console.ReadLine());
    
                return hgt;
            }
    
            static int Main()
            {
                Console.WriteLine(
    		"This application allows you to process a cylinder");
                Circle circ = Initialize();
                double height = GetHeight();
                Cylinder cldr = new Cylinder(circ.Radius, height);
    
                Console.WriteLine("\n================================");
                Console.WriteLine("=//=Cylinder Characteristics=//=");
                Console.WriteLine("================================");
                Console.WriteLine(" =-= Base Characteristics =-=");
                Console.WriteLine("--------------------------------");
                circ.Present();
                Console.WriteLine("------------------------------");
                Console.WriteLine("=-= Volume Characteristics =-=");
                cldr.Present();
                Console.WriteLine("================================\n");
               
                return 0;
            }
        }
    }
  19. Execute the application to sew the result. Here is an example:
     
    This application allows you to process a cylinder
    Enter the radius: 85.15
    Enter the height: 44.95
    
    ================================
    =//=Cylinder Characteristics=//=
    ================================
     =-= Base Characteristics =-=
    --------------------------------
    Radius:        85.15
    Diameter:      170.3
    Circumference: 535.012777
    Area:          22778.168980775
    ------------------------------
    =-= Volume Characteristics =-=
    Height:        44.95
    Lateral Area:  24048.82432615
    Total Area:    46826.993306925
    Volume:        1023879.5605199
    ================================
    
    Press any key to continue . . .
  20. Return to your programming environment

 

 

Previous Copyright © 2008-2011 FunctionX Next