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
{
}
Application:
Using Inheritance With Namespaces
|
|
- Start Microsoft Visual Studio
- To create a new application, on the main menu, click File -> New
Project...
- In the middle list, click Empty Project
- Change the Name to Geometry4 and press Enter
- To create a new class, on the main menu, click Project -> Add
Class...
- Set the Name to a Descriptor and press Enter
- Change the file as follows:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Geometry4
{
public abstract class Descriptor
{
public virtual string Describe()
{
return "A quadrilateral is a geometric figure " +
"that has four sides and four angles.";
}
}
}
- To create a new class, in the Class view, right-click Geometry4 ->
Add -> Class...
- Set the Name to Square and press Enter
- Change the file as follows:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Geometry4
{
public class Square : Descriptor
{
private double _side;
public Square(double s = 0.00D)
{
_side = s;
}
public string Name
{
get { return "Square"; }
}
public override string Describe()
{
// Get the introduction from the parent
string Introduction = base.Describe() +
"\nA square is a quadrilateral that has four " +
"equal sides and four right angles";
return Introduction;
}
}
}
- To create a new class, in the Class View, right-click Geometry4 ->
Add -> Class...
- Set the Name to Rectangle and press Enter
- Change the file as follows:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Geometry4
{
public class Rectangle : Descriptor
{
double _length;
double _height;
public Rectangle(double L = 0.00D, double H = 0.00D)
{
_length = L;
_height = H;
}
public string Name
{
get { return "Rectangle"; }
}
public override string Describe()
{
// Get the introduction from the parent
string Introduction = base.Describe();
string msg = Introduction +
"\nA rectangle is a quadrilateral that has adjacent " +
"perpendicular sides. This implies that its four " +
"angles are right.";
return msg;
}
}
}
- To create a new file, on the main menu, click Project -> Add New
Item...
- In the middle, click Code File
- Change the Name to Geometry and press Enter
- In the empty file, type the following:
using System;
using Geometry4;
public class Geometry
{
void DisplaySquare(Square s)
{
Console.WriteLine("Square Characteristics");
Console.WriteLine("Name: {0}", s.Name);
Console.WriteLine("Description: {0}", s.Describe());
}
void DisplayRectangle(Rectangle r)
{
Console.WriteLine("Rectangle Characteristics");
Console.WriteLine("Name: {0}", r.Name);
Console.WriteLine("Description: {0}", r.Describe());
}
public static int Main()
{
Square sq = new Square();
Geometry geo = new Geometry();
Rectangle rect = new Rectangle();
Console.WriteLine("========================================");
geo.DisplaySquare(sq);
Console.WriteLine("========================================");
geo.DisplayRectangle(rect);
Console.WriteLine("========================================");
Console.ReadKey();
return 0;
}
}
- To execute the application, on the Standard toolbar, click the Start
Debugging button
.
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.
========================================
- Press Enter to close the DOS window and return to your programming
environment
- On the main menu, click Project -> Add New Item...
- In the middle list, click Interface
- Set the Name to Quadrilateral
- Click Add
- Change the file as follows:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Geometry4
{
interface IQuadrilateral
{
}
}
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();
}
Application:
Creating Members of an Interface
|
|
Implementing an
Interface
|
|
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
{
}
Application:
Implementing an Interface
|
|
- On the main menu, click Project -> Add New Item...
- In the middle list, make sure Interface is selected (if not, select
it).
Set the Name to RightAngle
- Click Add
- Change the file as follows:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Geometry4
{
interface IRightAngle : IQuadrilateral
{
double Base { get; set; }
double Height { get; set; }
double Perimeter { get; }
}
}
- To access the Square.cs file, on the main menu, click Window ->
Square.cs
- Change the document as follows:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Geometry4
{
public class Square : Descriptor, IRightAngle
{
. . .
}
}
- On the main menu, click Window -> Rectangle.cs
- Change the Rectangle.cs file as follows:
using System;
namespace Geometry4
{
public class Rectangle : Descriptor, IRightAngle
{
. . .
}
}
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 implement 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
Application:
Implementing Derived Members of an Interface
|
|
- On top of the Code Editor, click the Square.cs label
- Change the file as follows:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Geometry4
{
public class Square : Descriptor, IRightAngle
{
private double _side;
public Square(double s = 0.00D)
{
_side = s;
}
public string Name
{
get { return "Square"; }
}
public override string Describe()
{
// Get the introduction from the parent, and add some
string Introduction = base.Describe() +
"\nA 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; }
}
}
}
- On top of the Code Editor, click the Rectangle.cs label
- Change it as follows:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Geometry4
{
public class Rectangle : Descriptor, IRightAngle
{
double _length;
double _height;
public Rectangle(double L = 0.00D, double H = 0.00D)
{
_length = L;
_height = H;
}
public string Name
{
get { return "Rectangle"; }
}
public override string Describe()
{
// Get the introduction from the parent
string Introduction = base.Describe();
// And add some
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); }
}
}
}
- On the main menu, click Window -> Geometry.cs
- Change the file as follows:
using System;
using Geometry4;
public class Geometry
{
public Square CreateSquare()
{
double side;
Console.Write("Enter the side of the square: ");
side = double.Parse(Console.ReadLine());
Square Sqr = new Square(side);
return Sqr;
}
public void DisplaySquare(Square s)
{
Console.WriteLine("Square Characteristics");
Console.WriteLine("Name: {0}", s.Name);
Console.WriteLine("Description: {0}", s.Describe());
Console.WriteLine("----------------------------");
Console.WriteLine("Side: {0}", s.Base);
Console.WriteLine("Perimeter: {0}", s.Perimeter);
Console.WriteLine("Area: {0}", s.Area);
}
public Rectangle CreateRectangle()
{
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;
}
public void DisplayRectangle(Rectangle r)
{
Console.WriteLine("Rectangle Characteristics");
Console.WriteLine("Name: {0}", r.Name);
Console.WriteLine("Description: {0}", r.Describe());
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);
}
public static int Main()
{
Square sq = new Square();
Geometry geo = new Geometry();
Rectangle rect = new Rectangle();
sq = geo.CreateSquare();
rect = geo.CreateRectangle();
Console.WriteLine("============================");
geo.DisplaySquare(sq);
Console.WriteLine("============================");
geo.DisplayRectangle(rect);
Console.WriteLine("============================");
Console.ReadKey();
return 0;
}
}
- To execute the application, on the Standard toolbar, click the Start
Debugging button
Enter the side of the square: 44.16
- Type the side of the square as follows 44.16
- Pres Enter
- Type the Base as 58.62 and press Enter
- Type the Height as 36.06
Enter the side of the square: 44.16
Enter the dimensions of the rectangle
Base: 58.62
Height: 36.06
- Press Enter:
============================
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 Enter to close the DOS window and return to your programming
environment
In previous sections, we saw that, to use an interface,
you must create a class that implements it. Here is an example of an
interface:
public interface IRound
{
double Radius { get; set; }
double Diameter { get; }
double Circumference { get; }
double Area { get; }
}
Here is a class that implements it:
public class Circle : IRound
{
protected double rad;
public Circle()
{
this.rad = 0.00D;
}
public Circle(double radius)
{
this.rad = radius;
}
public double Radius
{
get
{
return rad;
}
set
{
if (rad <= 0)
rad = 0;
else rad = value;
}
}
public double Diameter
{
get
{
return rad * 2;
}
}
public double Circumference
{
get
{
return rad * 2 * 3.14159;
}
}
public double Area
{
get
{
return rad * rad * 3.14159;
}
}
}
Remember that you can derive a class from a class that
implement an interface. Once the interface is ready, you can use it or a
class that implements it. As mentioned for an abstract class, you cannot
declare a variable of an interface type. In both cases (abstract classes and
interfaces), there are exceptions.
Declaring a Variable of Interface Type
|
|
You cannot declare a variable of an interface and use it
directly as you would for a class. The alternative to doing this is that you
can start declaring the variable by using the name of the interface and
giving a name to the variable. On the right side of the new
operator, you must use a class that implements that interface. Here is an
example:
using System;
public class Exercise
{
public static int Main()
{
IRound rnd = new Circle(Radius);
return 0;
}
}
After declaring the variable, you can access the members
of the class. The most important rule you must observe is that you can
access only the members that are part of the interface definition. Here is
an example:
using System;
public class Exercise
{
public static int Main()
{
double Radius = 0D;
Console.Write("Enter the radius: ");
Radius = double.Parse(Console.ReadLine());
IRound rnd = new Circle(Radius);
Console.WriteLine("Circle Characteristics");
Console.WriteLine("Radius: {0}", rnd.Radius);
Console.WriteLine("Diameter: {0}", rnd.Diameter);
Console.WriteLine("Circumference: {0}", rnd.Circumference);
Console.WriteLine("Area: {0}", rnd.Area);
return 0;
}
}
Here is an example of running the program:
Enter the radius: 44.27
Radius: 44.27
Circle Characteristics
Diameter: 88.54
Circumference: 278.1563786
Area: 6156.991440311
Press any key to continue . . .
If you had added new members to the class, you cannot
access those new members if you declare a variable using the interface.
Consider the following code:
File: Sphere.cs
public class Sphere : IRound
{
private double rad;
public Sphere(double radius = 0.00D)
{
this.rad = radius;
}
public double Radius
{
get
{
return rad;
}
set
{
if (rad <= 0)
rad = 0;
else rad = value;
}
}
public double Diameter
{
get
{
return rad * 2;
}
}
public double Circumference
{
get
{
return rad * 2 * 3.14159;
}
}
public double Area
{
get
{
return 4 * rad * rad * 3.14159;
}
}
public double Volume
{
get
{
return 4 * 3.14159 * rad * rad * rad / 3;
}
}
}
File: Exercise.cs
using System;
public class Exercise {
public static int Main()
{
double Radius = 0;
Console.Write("Enter the radius: ");
Radius = double.Parse(Console.ReadLine());
IRound rnd = new Sphere(Radius);
Console.WriteLine("Sphere Characteristics");
Console.WriteLine("Radius: {0}", rnd.Radius);
Console.WriteLine("Diameter: {0}", rnd.Diameter);
Console.WriteLine("Circumference: {0}", rnd.Circumference);
Console.WriteLine("Area: {0}", rnd.Area);
Console.WriteLine("Volume: {0}", rnd.Volume);
return 0;
}
}
This would produce the following error:
Error 1 'IRound' does not contain a definition for
'Volume' and no extension method 'Volume' accepting a first argument
of type 'IRound' could be found (are you missing a using directive or
an assembly reference?)
C:\Users\Administrateur\AppData\Local\Temporary Projects\Interfaces1\Exercise.cs
28 53 Interfaces1
Passing an Interface As Argument
|
|
If you are defining a method that receives an argument
and the argument can be the value of various objects that either inherit
from a common class or implement a common interface, instead of passing the
name of the class, you can pass either its parent class or the interface it
implements. To use this technique, each of the classes that will need the
benefits of the method must directly implement the interface (as the Circle
and the Sphere classes defined earlier do).
As mentioned in the previous section, when declaring a
variable using an interface, you can specify the name of the class after the
new operator. When calling the method, pass the name of the
variable as argument. Here are examples:
using System;
public class Exercise
{
public static void Present(IRound shape, string name = "Unspecified")
{
Console.WriteLine("{0} Characteristics", name);
Console.WriteLine("Radius: {0}", shape.Radius);
Console.WriteLine("Diameter: {0}", shape.Diameter);
Console.WriteLine("Circumference: {0}", shape.Circumference);
Console.WriteLine("Area: {0}", shape.Area);
}
public static int Main()
{
double Radius = 0;
Console.Write("Enter the radius: ");
Radius = double.Parse(Console.ReadLine());
Console.WriteLine("----------------------------");
IRound rnd = new Circle(Radius);
Present(rnd, "Circle");
Console.WriteLine();
rnd = new Sphere(Radius);
Present(rnd, "Sphere");
return 0;
}
}
Here is an example of running the program:
Enter the radius: 25.83
----------------------------
Circle Characteristics
Radius: 25.83
Diameter: 51.66
Circumference: 162.2945394
Area: 2096.033976351
Sphere Characteristics
Radius: 25.83
Diameter: 51.66
Circumference: 162.2945394
Area: 8384.135905404
Press any key to continue . . .
Notice that the compiler is able to distinguish each
object (the values of the calculated areas are different). Once again, when
accessing the members of the argument, remember that only the members
declared in the interface are available.
If you declare a variable using the name of a class, you
can still pass that variable to the method in the position held by the
interface. The rule to observe is that the class must inherit from the class
used as argument or it must implement it if it is an interface. Here are
examples:
using System;
public class Exercise
{
public static void Present(IRound shape, string name = "Unspecified")
{
Console.WriteLine("{0} Characteristics", name);
Console.WriteLine("Radius: {0}", shape.Radius);
Console.WriteLine("Diameter: {0}", shape.Diameter);
Console.WriteLine("Circumference: {0}", shape.Circumference);
Console.WriteLine("Area: {0}", shape.Area);
}
public static int Main()
{
double Radius = 0;
Console.Write("Enter the radius of the circle: ");
Radius = double.Parse(Console.ReadLine());
Circle circ = new Circle(Radius);
Present(circ, "Circle");
Console.WriteLine("----------------------------");
Console.Write("Enter the radius of the sphere: ");
Radius = double.Parse(Console.ReadLine());;
Sphere sph = new Sphere(Radius);
Present(sph, "Sphere");
Console.WriteLine("----------------------------");
return 0;
}
}
Here is an example of running the program:
Enter the radius of the circle: 44.25
Circle Characteristics
Radius: 44.25
Diameter: 88.5
Circumference: 278.030715
Area: 6151.429569375
----------------------------
Enter the radius of the sphere: 44.25
Sphere Characteristics
Radius: 44.25
Diameter: 88.5
Circumference: 278.030715
Area: 24605.7182775
----------------------------
Press any key to continue . . .
Checking the Compatibility of
an Object
|
|
Imagine you are accessing an object at one time but
don't know either what class it was declared from or what interface it
implements. To assist you with getting this information, you can use the
is operator. To use it, you can write a conditional
statement in the form:
if( value is Interface/Class )
Statement(s);
In the first part of the if condition,
enter the name of the object or variable that you want to test. The
is operator is followed by the name of an interface or class. If
the condition produces true, you can perform the Statement(s).
Otherwise, the Statement(s) will be ignored. Here are examples:
using System;
public class Exercise
{
public static void Present(IRound shape, string name = "Unspecified")
{
Console.WriteLine("{0} Characteristics", name);
Console.WriteLine("Radius: {0}", shape.Radius);
Console.WriteLine("Diameter: {0}", shape.Diameter);
Console.WriteLine("Circumference: {0}", shape.Circumference);
Console.WriteLine("Area: {0}", shape.Area);
}
public static int Main()
{
double Radius = 0;
Console.Write("Enter the radius: ");
Radius = double.Parse(Console.ReadLine());
Console.WriteLine("----------------------------");
IRound rnd = new Circle(Radius);
Present(rnd, "Circle");
if (rnd is Sphere) // rnd is not a Sphere object
Console.WriteLine("Volume: {0}", ((Sphere)rnd).Volume);
Console.WriteLine();
rnd = new Sphere(Radius);
Present(rnd, "Sphere");
if (rnd is Sphere ) // rnd is of type Sphere
Console.WriteLine("Volume: {0}", ((Sphere)rnd).Volume);
return 0;
}
}
Here is an example of running the program:
Enter the radius: 36.85
----------------------------
Circle Characteristics
Radius: 36.85
Diameter: 73.7
Circumference: 231.535183
Area: 4266.035746775
Sphere Characteristics
Radius: 36.85
Diameter: 73.7
Circumference: 231.535183
Area: 17064.1429871
Volume: 209604.556358212
Press any key to continue . . .
Application:
Ending the Lesson
|
|
- Close your programming environment
- When asked whether you want to save, click No
|
|