Implementing Interfaces
Recall that an interface is made up of a set of signatures, which in
turn
are made up of an operation’s
name
, the objects that it accepts as parameters, and its return values. The interface represents the entire set of
requests
that are sent to the interface. For example, by
typing
an interface, that is, Type IFCE, the interface accepts all requests for operations defined in that interface. Two objects representing the type can share individual
parts
of an interface. In addition, interfaces can contain other interfaces, referred to as
subsets
. Frequently, we can refer to a subtype as inheriting from its
supertype
interface.
Interfaces are fundamental to object-oriented programming. An interface represents an abstract concept by declaring its intentions, but never reveals the
how.
In essence, the interface says nothing about its implementation. This is a win-win situation for developers. They can
mutually
share the same interface and write totally unique
implementations
without conflict, as long as they
adhere
to the interface’s signature.
Dynamic Binding
Interfaces support dynamic binding for disparate objects sharing the same signature. For example, developers can submit a request to an object with confidence, knowing it will accept the request because it supports object substitutability. One object containing the same interface is interchangeable with another object at runtime,
courtesy
of a mechanism called polymorphism. As long as the object’s signature is adhered to, the object will process any request with equanimity.
During component-based development, you construct the interface so a client invocation on a specified service will never know
how
the request is implemented. Encapsulation
shields
the implementation from the client. Therefore, you can think of an interface as having two parts:
-
Interface
Defines a set of public method signatures but provides no implementations
-
Published interface
A uniquely identifiable interface made available through a registry to
clients
for dynamic discovery
Interfaces declared in Java or managed C++ typically provide only method signatures. Therefore, they describe
why
but not
how
the interface should be implemented. This allows for multiple implementations and allows services or
components
to enhance both flexibility and scalability. However, the stateless Internet environment does not guarantee that the interface’s implementation is always secure and compliant with any behavioral specification. Despite this limitation, businesses are gravitating toward more service-oriented systems. Perhaps it is possible to adhere to the safe practice of defining a behavioral interface.
Objects are created by instantiating a class. This process
allocates
storage for the object’s internal data consisting of instance
variables
. This in turn binds the object with its variable types. By
employing
a methodology called class inheritance, the subclass inherits all parent data type definitions and its behavioral characteristics. This means objects will perform operations defined in both the parent and child classes.
The sole purpose of an abstract class is to define a common interface for its child subclasses. However, an instance of this class can never be
instantiated
. Operations defined by an abstract class are called abstract operations, whereas classes that are not declared as abstract are called concrete classes.
Abstract classes
describe general behavioral characteristics, whereas
concrete classes
define more specific operations on an interface’s signature.
Class Inheritance vs. Interface Inheritance
It is important to distinguish between an object’s class and its type. A class defines an object’s internal state and provides information on how to implement it. For example, superclass Employer is inheritable by several subclass employee types. A salaried employee defines its implementation in reference to class Employer. An employee retained on commission defines its behavior in reference to class Employer, and so on. In essence, class inheritance is just a mechanism for implementing and extending a specified class’s functionality. To be a bit banal, a child inherits all genetic characteristics from his/her parents, but extends the parents’ genetic and social inclinations by building on them and becoming an individual person. Interface inheritance
reduces
implementation dependencies between subsystems and components. Therefore, it is safe to assume that programming to an interface is better than programming to an implementation. Best practices suggest it is better to declare variables that are instances of an abstract class rather than instances of a concrete class.
In conclusion, perhaps one of the most important concepts is learning how to design reusable components. In addition, knowing how to implement abstract interfaces is essential to designing web-based applications in ASP.NET. Remember, the .NET Framework and the ASP.NET runtime are
composed
of reusable components and interfaces. Therein lies the key to understanding .NET and ASP.NET.