Introduction to Polymorphism and Abstraction
Introduction to Polymorphism and Abstraction
Polymorphic Behaviors
Introduction
When you are creating a class, if you anticipate that a certain member should be redefined in a derived class, you can indicate this in your code. On the other hand, while creating a class that is based on another, if you find out that you are customizing a member that already exists in the base class, you should indicate, in your code, that you are providing a new version. In both cases, the common member should be created as virtual.
Practical Learning: Introcing Abstraction
namespace Quadrilaterals3 { internal class Square { public double Side { get; set; } public Square(double side) { Side = side; } public double Perimeter { get { return Side * 4.00; } } } }
A method is said to be virtual if it is anticipated to have different versions or implementations in classes that derive from it. To create a virtual method, you use a keyword named virtual. Therefore, to create a virtual method, in the base class, type the virtual keyword to the left of the return type of the method. If the method has an access level (private, public, or internal), the virtual keyword can appear before or after the access level.
Practical Learning: Creating Virtual Methods
namespace Quadrilaterals3
{
internal class Square
{
public double Side { get; set; }
public Square(double side)
{
Side = side;
}
public double Perimeter
{
get
{
return Side * 4.00;
}
}
public virtual double CalculateInradius()
{
return Side / 2.00;
}
}
}
Virtual Properties
A property of a class is virtual if it may be implemented in a derived class. This means that the property should primarily be created in its original class.
To get a virtual property, when creating the class, add the virtual keyword before the return type of the property.
Practical Learning: Creating a Virtual Property
namespace Quadrilaterals3
{
internal class Square
{
public double Side { get; set; }
public Square(double side)
{
Side = side;
}
public double Perimeter
{
get
{
return Side * 4.00;
}
}
public virtual double Area
{
get
{
return Side * Side;
}
}
public virtual double CalculateInradius()
{
return Side / 2.00;
}
}
}
using Quadrilaterals3 using static System.Console; double side = 0.00; WriteLine("================================================"); WriteLine("Geometry - Square"); WriteLine("================================================"); WriteLine("Enter the value to process a square"); WriteLine("------------------------------------------------"); try { Write("Side: "); side = double.Parse(ReadLine()!); } catch(FormatException ex) { WriteLine("The Side request produced an error, which is: " + ex.Message); } Square sqr = new Square(side); WriteLine("================================================"); WriteLine("Geometry - Square"); WriteLine("================================================"); WriteLine("Side: {0}", sqr.Side); WriteLine("Perimeter: {0}", sqr.Perimeter); WriteLine("Area: {0}", sqr.Area); WriteLine("Inscribed Radius: {0}", sqr.CalculateInradius()); WriteLine("================================================");
================================================ Geometry - Square ================================================ Enter the value to process a square ------------------------------------------------ Side: 429.63 ================================================ Geometry - Square ================================================ Side: 429.63 Perimeter: 1718.52 Area: 184581.9369 Inscribed Radius: 214.815 ================================================ Press any key to close this window . . .
namespace Volumetrics6 { internal class Rectangle { public double Width { get; set; } public double Height { get; set; } public Rectangle(double width, double height) { Width = width; Height = height; } } }
namespace Volumetrics6 { internal class Box : Rectangle { public Box(double width, double height, double length) : base(width, height) { Length = length; } public double Length { get; set; } } }
using static System.Console; using Volumetrics6; using Exercise1; using static System.Console; WriteLine("================================================"); WriteLine("Geometry - Square"); WriteLine("================================================"); WriteLine("Enter the value to process a square"); WriteLine("------------------------------------------------"); void Show(Box box) { WriteLine("================================================"); WriteLine("Geometry - Rectangular Box"); WriteLine("================================================"); WriteLine("Width: {0}", box.Width); WriteLine("Height: {0}", box.Height); WriteLine("Length: {0}", box.Length); WriteLine("================================================"); } Box Create() { double width = 0.00, height = 0.00, length = 0.00; WriteLine("================================================"); WriteLine("Geometry - Rectangular Box"); WriteLine("================================================"); WriteLine("Enter the values to process a box"); WriteLine("------------------------------------------------"); try { Write("Width: "); width = double.Parse(ReadLine()!); } catch(FormatException ex) { WriteLine("There was a problem with the value of the width. Please report the error as: " + ex.Message); } try { Write("Height: "); height = double.Parse(ReadLine()!); } catch (FormatException ex) { WriteLine("There was a problem with the value of the height. Please report the error as: " + ex.Message); } try { Write("Length: "); length = double.Parse(ReadLine()!); } catch (FormatException ex) { WriteLine("There was a problem with the value of the length. Please report the error as: " + ex.Message); } return new Box(width, height, length); } Box creator = Create(); Show(creator);
================================================ Geometry - Rectangular Box ================================================ Enter the value to process a box ------------------------------------------------ Width: 863.69 Height: 527.58 Length: 1406.97 ================================================ Geometry - Rectangular Box ================================================ Width: 863.69 Height: 527.58 Length: 1406.97 ================================================ Press any key to close this window . . .
Overriding a Member in a Derived Class
As seen in previous sections, you can create a virtual method or property in a class and use it like any other method or property of its class. As mentioned in our introduction, the essence of creating a virtual method or property is to provide a different implementation of that member in its own and in classes that derive from that class. Providing a different version of a member or property in a derived class is referred to as overriding the method or property.
To override a method, in a derived class, create a method with the same syntax (same return type, same name, and same parameter(s) if any) as the method in the parent class. This time, replace the virtual keyword with the override keyword. In the same way, to override a propertty, create one of the same return type and name in the derived class but use the override keyword instead of the the virtual keyword.
Practical Learning: Overriding a Method in a Derived Class
namespace Volumetrics6
{
internal class Rectangle
{
public double Width { get; set; }
public double Height { get; set; }
public Rectangle(double width, double height)
{
Width = width;
Height = height;
}
public virtual double CalculateArea()
{
return Width * Height;
}
}
}
namespace Volumetrics6
{
internal class Box : Rectangle
{
public Box(double width, double height, double length)
: base(width, height)
{
Length = length;
}
public double Length { get; set; }
public override double CalculateArea()
{
double face = base.CalculateArea();
double side = base.Height * this.Length;
double top = base.Width * this.Length;
return (face * 2) + (side * 2) + (top * 2);
}
}
}
using static System.Console;
using Volumetrics6;
WriteLine("================================================");
WriteLine("Geometry - Square");
WriteLine("================================================");
WriteLine("Enter the value to process a square");
WriteLine("------------------------------------------------");
void Show(Box box)
{
WriteLine("================================================");
WriteLine("Geometry - Rectangular Box");
WriteLine("================================================");
WriteLine("Width: {0}", box.Width);
WriteLine("Height: {0}", box.Height);
WriteLine("Length: {0}", box.Length);
WriteLine("------------------------------------------------");
WriteLine("Total Area: {0}", box.CalculateArea());
WriteLine("================================================");
}
Box Create()
{
double width = 0.00, height = 0.00, length = 0.00;
WriteLine("================================================");
WriteLine("Geometry - Rectangular Box");
WriteLine("================================================");
WriteLine("Enter the values to process a box");
WriteLine("------------------------------------------------");
try
{
Write("Width: ");
width = double.Parse(ReadLine()!);
}
catch(Exception ex) when (ex is FormatException ex)
{
WriteLine("There was a problem with the value of the width. Please report the error as: " + ex.Message);
}
try
{
Write("Height: ");
height = double.Parse(ReadLine()!);
}
catch (Exception ex) when (ex is FormatException ex)
{
WriteLine("There was a problem with the value of the height. Please report the error as: " + ex.Message);
}
try
{
Write("Length: ");
length = double.Parse(ReadLine()!);
}
catch (Exception ex) when (ex is FormatException ex)
{
WriteLine("There was a problem with the value of the length. Please report the error as: " + ex.Message);
}
return new Box(width, height, length);
}
Box creator = Create();
Show(creator);
================================================ Geometry - Rectangular Box ================================================ Enter the value to process a box ------------------------------------------------ Width: 863.69 Height: 527.58 Length: 1406.97 ================================================ Geometry - Rectangular Box ================================================ Width: 863.69 Height: 527.58 Length: 1406.97 ------------------------------------------------ Total Area: 4826281.444200001 ================================================ Press any key to close this window . . .
Foundations of Abstract Classes
Introduction
A class is said to be abstract if its primary role is to serve as parent for other classes. This means that another class must be derived from the abstract class. After that, the abstract class can be used somehow in an application.
Practical Learning: Introducing Class Abstraction
namespace GasUtilityCompany1 { internal class BillPreparation { public int InvoiceNumber { get; set; } public double CounterReadingStart { get; set; } public double CounterReadingEnd { get; set; } public double CCFTotal { get { return CounterReadingEnd - CounterReadingStart; } } public double TotalTherms { get { return CCFTotal * 1.0367; } } public double DistributionAdjustment { get { return TotalTherms * 0.13086; } } public double CalculateTransportationCharges() { if (TotalTherms <= 5000) return TotalTherms * 0.016289; else return TotalTherms * 0.009577; } public double CalculateDeliveryTotal() { double first50Therms = 0, over50Therms = 0; if (TotalTherms < 5000) { first50Therms = TotalTherms * 0.05269; over50Therms = 0; } else { first50Therms = 5000 * 0.5269; over50Therms = (TotalTherms - 5000) * 0.04995; } return CalculateTransportationCharges() + DistributionAdjustment + first50Therms + over50Therms; } public double EnvironmentalCharges { get { return CalculateDeliveryTotal() * 0.0045; } } public double AmountDue { get { return CalculateDeliveryTotal() + EnvironmentalCharges; } } } }
using static System.Console; using GasUtilityCompany1; using Exercise1; using static System.Console; BillPreparation bp = new BillPreparation(); WriteLine("Gas Utility Company - Customer Invoice Preparation"); WriteLine("======================================================"); WriteLine("To prepare an invoice, enter the following information"); try { Write("Invoice #: "); bp.InvoiceNumber = int.Parse(ReadLine()!); } catch (FormatException ex) { WriteLine("The value for the invoice number is not right. The error is: " + ex.Message); } try { Write("Counter Reading Start: "); bp.CounterReadingStart = double.Parse(ReadLine()!); } catch (FormatException ex) { WriteLine("The starting value of the gas counter is not right. The error is: " + ex.Message); } try { Write("Counter Reading End: "); bp.CounterReadingEnd = double.Parse(ReadLine()!); } catch (FormatException ex) { WriteLine("The ending value of the gas counter is not right. The error is: " + ex.Message); } WriteLine("======================================================"); WriteLine("Gas Utility Company - Customer Invoice"); WriteLine("======================================================"); WriteLine("Gas Meter Reading"); WriteLine("------------------------------------------------------"); WriteLine("Invoice Number: {0,10}", bp.InvoiceNumber); WriteLine("Counter Reading Start: {0,10}", bp.CounterReadingStart); WriteLine("Counter Reading End: {0,10}", bp.CounterReadingEnd); WriteLine("======================================================"); WriteLine("Gas Consumption Evaluation"); WriteLine("------------------------------------------------------"); WriteLine("CCF Total: {0,10:n}", bp.CCFTotal); WriteLine("Total Therms: {0,10:n}", bp.TotalTherms); WriteLine("Distribution Adjustment: {0,10:n}", bp.DistributionAdjustment); WriteLine("======================================================"); WriteLine("Bill Values"); WriteLine("------------------------------------------------------"); WriteLine("Transportation Charges: {0,10:n}", bp.CalculateTransportationCharges()); WriteLine("Delivery Total: {0,10:n}", bp.CalculateDeliveryTotal()); WriteLine("Environmental Charges: {0,10:n}", bp.EnvironmentalCharges); WriteLine("------------------------------------------------------"); WriteLine("Amount Due: {0,10:n}", bp.AmountDue); WriteLine("======================================================");
Gas Utility Company - Customer Invoice Preparation ====================================================== To prepare an invoice, enter the following information Invoice #: 100001 Counter Reading Start: 214485 Counter Reading End: 215057 ====================================================== Gas Utility Company - Customer Invoice ====================================================== Gas Meter Reading ------------------------------------------------------ Invoice Number: 100001 Counter Reading Start: 214485 Counter Reading End: 215057 ====================================================== Gas Consumption Evaluation ------------------------------------------------------ CCF Total: 572.00 Total Therms: 592.99 Distribution Adjustment: 77.60 ====================================================== Bill Values ------------------------------------------------------ Transportation Charges: 9.66 Delivery Total: 118.50 Environmental Charges: 0.53 ------------------------------------------------------ Amount Due: 119.04 ====================================================== Press any key to close this window . . .
namespace GasUtilityCompany1 { internal class CustomerInvoice { } }
To get an abstract class, you use a keyword named abstract. Therefore, to create an abstract class, type this keyword to the left of the class keyword. Here is an example:
abstract class Triangle
{
}
If you decide to apply an access level (public or internal) on the class creation, the abstract keyword can appear before or after the access level.
In the class, you can add any type of member, like any of the types of constructors, methods, or properties we have used so far.
Practical Learning: Creating an Abstract Class
namespace GasUtilityCompany1
{
internal abstract class BillPreparation
{
public int InvoiceNumber { get; set; }
public double CounterReadingStart { get; set; }
public double CounterReadingEnd { get; set; }
public double CCFTotal
{
get => CounterReadingEnd - CounterReadingStart;
}
public double TotalTherms
{
get => CCFTotal * 1.0367;
}
public double DistributionAdjustment
{
get => TotalTherms * 0.13086;
}
public double CalculateTransportationCharges()
{
return (TotalTherms <= 5000) ? (TotalTherms * 0.016289) : (TotalTherms * 0.009577);
}
public double CalculateDeliveryTotal()
{
double first50Therms = 0, over50Therms = 0;
if (TotalTherms < 5000)
{
first50Therms = TotalTherms * 0.05269;
over50Therms = 0;
}
else
{
first50Therms = 5000 * 0.5269;
over50Therms = (TotalTherms - 5000) * 0.04995;
}
return CalculateTransportationCharges() + DistributionAdjustment + first50Therms + over50Therms;
}
public double EnvironmentalCharges
{
get => CalculateDeliveryTotal() * 0.0045;
}
public double AmountDue
{
get => CalculateDeliveryTotal() + EnvironmentalCharges;
}
}
}
Severity Code Description Project File Line Suppression State Error CS0144 Cannot create an instance of the abstract type or interface 'BillPreparation' GasUtilityCompany1 . . .
Deriving from an Abstract Class
An abstract class cannot be directly used like any of the classes we have used so far. This means that you cannot use a constructor of an abstract class to instantiate an object. You have various solutions to solve this problem. The first thing you must do is to create a class derived from the abstract class. You can then create an object of that class.
Practical Learning: Deriving from an Abstract Class
namespace GasUtilityCompany1
{
internal class CustomerInvoice : BillPreparation
{
}
}
An Object of an Abstract Class
Although you must always derive a class from an abstract class in order to make the abstract class useful, you can declare a variable of an abstract class. Such a variable must be initialized with a constructor of a class derived from the abstract class.
Practical Learning: Deriving from an Abstract Class
using static System.Console;
using GasUtilityCompany1;
BillPreparation bp = new CustomerInvoice();
WriteLine("Gas Utility Company - Customer Invoice Preparation");
WriteLine("======================================================");
WriteLine("To prepare an invoice, enter the following information");
Random rndNumber = new Random();
bp.InvoiceNumber = rndNumber.Next(100000, 999999);
try
{
Write("Counter Reading Start: ");
bp.CounterReadingStart = double.Parse(ReadLine()!);
}
catch (Exception ex) when (ex is FormatException ex)
{
WriteLine("The starting value of the gas counter is not right. The error is: " + ex.Message);
}
try
{
Write("Counter Reading End: ");
bp.CounterReadingEnd = double.Parse(ReadLine()!);
}
catch (Exception ex) when (ex is FormatException ex)
{
WriteLine("The ending value of the gas counter is not right. The error is: " + ex.Message);
}
WriteLine("======================================================");
WriteLine("Gas Utility Company - Customer Invoice");
WriteLine("======================================================");
WriteLine("Gas Meter Reading");
WriteLine("------------------------------------------------------");
WriteLine("Invoice Number: {0,10}", bp.InvoiceNumber);
WriteLine("Counter Reading Start: {0,10}", bp.CounterReadingStart);
WriteLine("Counter Reading End: {0,10}", bp.CounterReadingEnd);
WriteLine("======================================================");
WriteLine("Gas Consumption Evaluation");
WriteLine("------------------------------------------------------");
WriteLine("CCF Total: {0,10:n}", bp.CCFTotal);
WriteLine("Total Therms: {0,10:n}", bp.TotalTherms);
WriteLine("Distribution Adjustment: {0,10:n}", bp.DistributionAdjustment);
WriteLine("======================================================");
WriteLine("Bill Values");
WriteLine("------------------------------------------------------");
WriteLine("Transportation Charges: {0,10:n}", bp.CalculateTransportationCharges());
WriteLine("Delivery Total: {0,10:n}", bp.CalculateDeliveryTotal());
WriteLine("Environmental Charges: {0,10:n}", bp.EnvironmentalCharges);
WriteLine("------------------------------------------------------");
WriteLine("Amount Due: {0,10:n}", bp.AmountDue);
WriteLine("======================================================");
Gas Utility Company - Customer Invoice Preparation ====================================================== To prepare an invoice, enter the following information Counter Reading Start: 6921 Counter Reading End: 7248 ====================================================== Gas Utility Company - Customer Invoice ====================================================== Gas Meter Reading ------------------------------------------------------ Invoice Number: 368290 Counter Reading Start: 6921 Counter Reading End: 7248 ====================================================== Gas Consumption Evaluation ------------------------------------------------------ CCF Total: 327.00 Total Therms: 339.00 Distribution Adjustment: 44.36 ====================================================== Bill Values ------------------------------------------------------ Transportation Charges: 5.52 Delivery Total: 67.75 Environmental Charges: 0.30 ------------------------------------------------------ Amount Due: 68.05 ====================================================== Press any key to close this window . . .
A Parameter of an Abstract Class
As done for any class, you can create a function or method that uses a parameter of an abstract class. In the body of the function, use the parameter like any other. For example, you can access the members of the abstract class.
When calling a method that uses a parameter of an abstract class, the argument you pass must hold an appropriate value, which should be an object of a class derived from the abstract class.
Practical Learning: Passing an Object of an Abstract Type
using static System.Console; using GasUtilityCompany1; void PresentInvoice(BillPreparation values) { WriteLine("======================================================"); WriteLine("Gas Utility Company - Customer Invoice"); WriteLine("======================================================"); WriteLine("Gas Meter Reading"); WriteLine("------------------------------------------------------"); WriteLine("Invoice Number: {0,10}", values.InvoiceNumber); WriteLine("Counter Reading Start: {0,10}", values.CounterReadingStart); WriteLine("Counter Reading End: {0,10}", values.CounterReadingEnd); WriteLine("======================================================"); WriteLine("Gas Consumption Evaluation"); WriteLine("------------------------------------------------------"); WriteLine("CCF Total: {0,10:n}", values.CCFTotal); WriteLine("Total Therms: {0,10:n}", values.TotalTherms); WriteLine("Distribution Adjustment: {0,10:n}", values.DistributionAdjustment); WriteLine("======================================================"); WriteLine("Bill Values"); WriteLine("------------------------------------------------------"); WriteLine("Transportation Charges: {0,10:n}", values.CalculateTransportationCharges()); WriteLine("Delivery Total: {0,10:n}", values.CalculateDeliveryTotal()); WriteLine("Environmental Charges: {0,10:n}", values.EnvironmentalCharges); WriteLine("------------------------------------------------------"); WriteLine("Amount Due: {0,10:n}", values.AmountDue); WriteLine("======================================================"); } BillPreparation bp = new CustomerInvoice(); WriteLine("Gas Utility Company - Customer Invoice Preparation"); WriteLine("======================================================"); WriteLine("To prepare an invoice, enter the following information"); Random rndNumber = new Random(); bp.InvoiceNumber = rndNumber.Next(100000, 999999); try { Write("Counter Reading Start: "); bp.CounterReadingStart = double.Parse(ReadLine()!); } catch (Exception ex) when (ex is Exception ex) when (ex is FormatException ex) { WriteLine("The starting value of the gas counter is not right. The error is: " + ex.Message); } try { Write("Counter Reading End: "); bp.CounterReadingEnd = double.Parse(ReadLine()!); } catch (Exception ex) when (ex is Exception ex) when (ex is FormatException ex) { WriteLine("The ending value of the gas counter is not right. The error is: " + ex.Message); } PresentInvoice(bp);
Gas Utility Company - Customer Invoice Preparation ====================================================== To prepare an invoice, enter the following information Counter Reading Start: 585702 Counter Reading End: 586227 ====================================================== Gas Utility Company - Customer Invoice ====================================================== Gas Meter Reading ------------------------------------------------------ Invoice Number: 637118 Counter Reading Start: 585702 Counter Reading End: 586227 ====================================================== Gas Consumption Evaluation ------------------------------------------------------ CCF Total: 525.00 Total Therms: 544.27 Distribution Adjustment: 71.22 ====================================================== Bill Values ------------------------------------------------------ Transportation Charges: 8.87 Delivery Total: 108.77 Environmental Charges: 0.49 ------------------------------------------------------ Amount Due: 109.26 ====================================================== Press any key to close this window . . .
Returning an Object of Abstract Type
You can create a function or method that returns an object of an abstract class type. Make sure the function returns an object of that type. Outside the class, when calling the function, you can assign it to a variable of the abstract class.
Practical Learning: Creating an Object of Abstract Type
using static System.Console; using GasUtilityCompany1; void PresentInvoice(BillPreparation values) { WriteLine("======================================================"); WriteLine("Gas Utility Company - Customer Invoice"); WriteLine("======================================================"); WriteLine("Gas Meter Reading"); WriteLine("------------------------------------------------------"); WriteLine("Invoice Number: {0,10}", values.InvoiceNumber); WriteLine("Counter Reading Start: {0,10}", values.CounterReadingStart); WriteLine("Counter Reading End: {0,10}", values.CounterReadingEnd); WriteLine("======================================================"); WriteLine("Gas Consumption Evaluation"); WriteLine("------------------------------------------------------"); WriteLine("CCF Total: {0,10:n}", values.CCFTotal); WriteLine("Total Therms: {0,10:n}", values.TotalTherms); WriteLine("Distribution Adjustment: {0,10:n}", values.DistributionAdjustment); WriteLine("======================================================"); WriteLine("Bill Values"); WriteLine("------------------------------------------------------"); WriteLine("Transportation Charges: {0,10:n}", values.CalculateTransportationCharges()); WriteLine("Delivery Total: {0,10:n}", values.CalculateDeliveryTotal()); WriteLine("Environmental Charges: {0,10:n}", values.EnvironmentalCharges); WriteLine("------------------------------------------------------"); WriteLine("Amount Due: {0,10:n}", values.AmountDue); WriteLine("======================================================"); } BillPreparation PrepareInvoice() { BillPreparation prep = new CustomerInvoice(); WriteLine("Gas Utility Company - Customer Invoice Preparation"); WriteLine("======================================================"); WriteLine("To prepare an invoice, enter the following information"); Random rndNumber = new Random(); prep.InvoiceNumber = rndNumber.Next(100000, 999999); try { Write("Counter Reading Start: "); prep.CounterReadingStart = double.Parse(ReadLine()!); } catch (Exception ex) when (ex is FormatException ex) { WriteLine("The starting value of the gas counter is not right. The error is: " + ex.Message); } try { Write("Counter Reading End: "); prep.CounterReadingEnd = double.Parse(ReadLine()!); } catch (Exception ex) when (ex is FormatException ex) { WriteLine("The ending value of the gas counter is not right. The error is: " + ex.Message); } return prep; } BillPreparation bp = PrepareInvoice(); PresentInvoice(bp);
Gas Utility Company - Customer Invoice Preparation ====================================================== To prepare an invoice, enter the following information Counter Reading Start: 1874 Counter Reading End: 3139 ====================================================== Gas Utility Company - Customer Invoice ====================================================== Gas Meter Reading ------------------------------------------------------ Invoice Number: 131107 Counter Reading Start: 1874 Counter Reading End: 3139 ====================================================== Gas Consumption Evaluation ------------------------------------------------------ CCF Total: 1,265.00 Total Therms: 1,311.43 Distribution Adjustment: 171.61 ====================================================== Bill Values ------------------------------------------------------ Transportation Charges: 21.36 Delivery Total: 262.07 Environmental Charges: 1.18 ------------------------------------------------------ Amount Due: 263.25 ====================================================== Press any key to close this window . . .
The Members of an Abstract Class
Introduction
Consider a class as follows:
public abstract class Triangle { public double Base { get; set; } public virtual double Height { get; set; } public double Area { get { return Base * Height / 2.00; } } }
Consider a derived class follows:
internal class Equilateral : Triangle { readonly double Angle; public Equilateral() { Angle = 60; } public double Side { get { return Base; } } }
Like a normal class, an abstract class can contain virtual methods and properties. As seen for non-abstract classes, if you create a virtual member in an abstract class, an object of the derived class can directly use that member. On the other hand, if you want the derived class to provide a different version of the virtual member, you must override it in the child class. This is done exactly as seen for non-abstract classes.
An Abstract Method
A method is said to be abstract if its class doesn't implement that method but the derived class must implement it. An abstract method can only belong to an abstract class.
To create an abstract method, apply the following rules:
After creating an abstract method, every class that derives from that class must provide an implementation of (each of) the abstract method(s). To implement the method, you must apply the override keyword to it as we reviewed for virtual methods.
Remember that an abstract method must not have a body. If you want the method to have a body, you can mark it with the virtual keyword. Here is an example:
public abstract class Triangle
{
public double Base { get; set; }
public virtual double Height { get; set; }
public double Area
{
get
{
return Base * Height / 2.00;
}
}
public abstract double CalculatePerimeter();
}
Here is an example of overriding the abstract method:
internal class Equilateral : Triangle
{
readonly double Angle;
public Equilateral()
{
Angle = 60;
}
public double Side
{
get
{
return Base;
}
}
public override double CalculatePerimeter()
{
return Side * 3.00;
}
}
An Abstract Property
A property is abstract if its class doesn't include an implementation of that property. Any class based on the abstract class must implement the abstract property using the override keyword.
If you want to create an abstract property that has only a get accessor, the property must use the abstract keyword. Here is an example:
public abstract class GeometricFigure
{
public abstract double Perimeter { get; }
}
If the property has both a get and a set accessors, it can use either the abstract or the virtual keyword. Here are examples:
public abstract class GeometricFigure { public abstract double Median { get; set; } public virtual double Perimeter { get; set; } }
Having Many Methods that Return the Same Type of Abstract Object
Consider an abstract class as follows::
public abstract class Triangle { public double Angle1 { get; set; } public double Angle2 { get; set; } public double Side1 { get; set; } }
Imagine you have a method that returns an object of this abstract class. Here is an example:
public abstract class Triangle
{
public double Angle1 { get; set; }
public double Angle2 { get; set; }
public double Side1 { get; set; }
}
internal class Oblique : Triangle
{
public Triangle View()
{
Triangle ot = new Oblique();
return ot;
}
}
If you need to have one or more other methods that perform the same type(s) of operation(s) and/or return the same type of object, you don't need to declare a variable to call the first method. Here are examples:
public abstract class Triangle { public double Angle1 { get; set; } public double Angle2 { get; set; } public double Side1 { get; set; } } internal class Oblique : Triangle { public Triangle View() { Triangle ot = new Oblique(); return ot; } public Triangle Calculate() { return View(); } public Triangle Evaluate() { return View(); } public Triangle Summarize() { return View(); } }
Practical Learning: Ending the Lesson
|
|||
Previous | Copyright © 2002-2024, FunctionX | Saturday 12 March 2022, 10:36 AM | Next |
|