Sie sind auf Seite 1von 16

UNIT I

Object oriented thinking :- Need for oop paradigm, A way of viewing world – Agents,
responsibility, messages, methods, classes and instances, class hierarchies (Inheritance),
method binding, overriding and exceptions, summary of oop concepts, coping with
complexity, abstraction mechanisms

Need for OOP paradism

One of the most important characteristics of OOP (Object Oriented Programming) is the
data encapsulation concept, which means that there is a very close attachment between
data items and procedures. The procedures (methods) are responsible for manipulating
the data in order to reflect its behaviour. The public interface, formed by the collections
of messages understood by an object, completely defines how to use this object.
Programs that want to manipulate an object, only have to be concerned about which
messages this object understands, and do not have to worry about how these tasks are
achieved nor the internal structure of the object. The hiding of internal details makes an
object abstract, and the technique is normally known as data abstraction. Normally,
objects of a given type are instances of a class, whose definition specifies the private
(internal) working of these objects as well as their public interface. Basically the creation
of an object is referred to as instantiation, and it consists of a class definition with
appropriate initial values.

Another powerful feature of OOP, is the concept of inheritance (derived classes in C++),
meaning the derivation of a similar or related object (the derived object) from a more
general based object. The derived class can inherit the properties of its base class and also
adds its own data and routines. The concept above is known as single inheritance, but it is
also possible to derive a class from several base classes, which is known as multiple
inheritance. Overloading, in OOP, means the ability to assign multiple meanings to the
names of operators and functions. For example, the operator +, normally associated with
arithmetic addition can be overloaded to add one list to another in a certain context.
Polymorphism means the sending of a message to an object without concern about how
the software is going to accomplish the task, and furthermore it means that the task can
be executed in completely different ways depending on the object that receives the
message (in C++, polymorphism is implemented through the use of virtual functions).
When the decision as to which actions are going to be executed is made at run-time, the
polymorphism is referred to as late binding (as in the case of virtual functions). If they
are made at compile time then it is known as early binding.

After this brief introduction, we now describe the major advantages of OOP.

• simplicity: software objects model real world objects, so the complexity is


reduced and the program structure is very clear;
• modularity: each object forms a separate entity whose internal workings are
decoupled from other parts of the system;
• modifiability: it is easy to make minor changes in the data representation or the
procedures in an OO program. Changes inside a class do not affect any other part
of a program, since the only public interface that the external world has to a class
is through the use of methods;
• extensibility: adding new features or responding to changing operating
environments can be solved by introducing a few new objects and modifying
some existing ones;
• maintainability: objects can be maintained separately, making locating and fixing
problems easier;
• re-usability: objects can be reused in different programs.

A way of viewing world

To illustrate some of the major ideas in object-oriented programming, consider how we


might go about handling a real world situation . Suppose I wish to send flowers to my
grandmother (Elsa) for her birthday. She lives far away (Orocovis) so doing it myself is
out of the question. However, sending her flowers is easy, I go to my local florist (Flora),
tell her the kinds of flowers, the number and the address, and I can be assured the flowers
will be delivered.
Mechanism Used to Solve Problem:
1. Find an appropriate agent (Flora)
2. Pass to her a message containing my request
3. It is the responsibility of Flora to satisfy my request.
4. There is some method – some algorithm or set of operations – used by Flora to do this
5. I do not need to know (or want to know) the particular method she will use. This
information is usually hidden from my inspection. Flora probably delivers a slightly
different message to another florist in Orocovis. That florist, in turn, makes the
arrangement and passes it, along with another message, to a delivery person, and so on.
First Principle of Object-Oriented problem solving is the vehicle by which activities are
initiated:
Action is initiated in OOP by sending a message to and agent (object) responsible for that
action. The message encodes the request for an action and is accompanied by any
additional info (arguments) needed to carry out the request. If the receiver accepts the
message, it accepts the responsibility to carry out the indicated action. In response to a
message, the receiver will perform some method to satisfy the request.
We have noted the important principle of information hiding in regard to message
passing – that is, the client sending the request need not know the actual means by which
the request will be honored. Information hiding is also present in other conventional
languages. In what sense is a message different form a procedure call?
 T here is a designated receiver (agent to which the message is sent).
The interpretation of the message (method used to respond to the msg) depends on the
receiver.
Usually, the specific receiver for any given msg will not be known until run time (so the
method to invoke cannot be determined until then). Thus, we say there is a late binding
between the msg and the code used to respond to the msg.
Responsibilities
A fundamental concept in OOP is to describe behavior in terms of responsibilities. By
discussing a problem in terms of responsibilities we increase the level of abstraction.
When you make an object responsible for specific actions, you expect certain behavior.
But just as important, responsibility implies a degree of independence or noniterference.
The entire collection of responsibilities associated with an object is often described by the
term protocol.

Classes and Instances


Although I have only dealt with Flora a few times, I have a rough idea of the behavior I
can expect when I go into her shop and present her with my request. I have some
information about florist in general, and Flora, being an instance of this category (or
class), will fit the general pattern.

All objects are instances of a class.


The method invoked by an object in response to a message is determined by the class of
the receiver. All objects of a given class use the same method in response to similar
messages.

Class Hierarchies
There is more information about Flora, not necessarily because she is a florist, but
because she is a shopkeeper. The knowledge of Flora is organized in terms of a hierarchy
of categories. Flora is a Florist, but Florist is a specialized form of Shopkeeper. A
Shopkeeper is a Human . . The principle that knowledge of a more general category is
also applicable to a more specific category is called inheritance. The class Florist will
inherit attributes of the class Shopkeeper.
CRC CARDS
• It is often useful, when you are designing an object-oriented application, to think about
the process as being similar to organizing a group of individuals, such as a club or
association. If any particular actions is to happen, somebody must be responsible for
doing it. No action takes place without an agent performing the action. One objective of
object-oriented design is first to establish who is responsible for each action that is to be
performed.
• One technique that is very useful is the use of index cards to represent individual
classes. Such cards are known as CRC card, since they are divided into three
components: class, responsibility, and collaboration.
• The purpose of the methodology is to provide a framework in which an initial set of
classes, their variables, and methods can be specified for a new application. The utility of
the method is the assistance it gives users in organizing their thoughts about how to
structure an application.
• This kind of decomposition is a first step in understanding how a problem can be
separated into parts.

CLASS
• The upper-left corner of each CRC card contains the name of the class being described.
The selection of meaningful names is extremely important, as the class name create the
vocabulary with which the design will be formulated. Shakespeare could claim that a
change in the name of an object will not alter the physical characteristics of the entity so
denoted, but it is certainly not the case that all names will conjure up the same mental
images to the listener.
• Names should be internally consistent, meaningful, preferably short, and evocative in
the context of the problem at hand.

RESPONSIBILITIES
• Immediately below the class name on the CRC card, the responsibilities of the class are
listed. Responsibilities describe the problem to be solved. They should be expressed by
short verb phrases, each containing an active verb.
• Responsibilities should describe what is to be done, and should avoid detailed
specifications of how each task is to be accomplished.

COLLABORATORS
• Few objects can perform useful operations entirely on their own. Almost all stand in
some relationship to several others, either as providers or as requesters of a service or
facility.
• The list of collaborators should include all classes of which the class being described
needs to be aware. It should certainly include classes that provide services needed to meet
the responsibilities of the class being described. It could also, but need not to, include
classes that require services provided by the described class.
• The decision whether to list another class as a collaborator is based on the degree of
connection or cooperation.
Ex: A special type of Window may be tied symmetrically to the data being displayed,
and thus would be considered a collaborator. Ex: A Stack may not care at all to whom it
is providing services, and thus need not list its caller as a collaborator (although the caller
should list the stack as a collaborator).

Discovering Classes
One of the first decisions that must be made in creating an OO application is the selection
of classes.
The following categories cover the majority of types of classes:
• Data Managers, Data, or State: These are classes whose principle responsibility is to
maintain data or state information. Ex: In a card game application the class Card will hold
the rank and the suit of the card.
• Data Sinks, Data Sources: Classes that generate data (random number generator), or
accept data and then process them further (class to perform output to disk or file). Unlike
the data managers they do not hold the data for any period of time, but generates it on
demand (for a data source), or processes it when called upon (for a data sink).
•View or Observer: An essential portion of most applications is the display of info on an
output device. Because the code for these activities is often complex, frequently
modified, and largely independent of the actual data being displayed, it is good
programming practice to isolate display behavior in separate classes form those classes
that maintain the data being displayed.
Ex: For the card application we may create CardView to take care of writing a card image
on a screen. Often the base data is called the model, and the display class the
view.Because we separate the object being viewed (model) from the view that displays
the visual representation of that object, the design of the model and the display system are
usually greatly simplified. Ideally, the model should neither require nor contain any info
about the view. This facilitates code reuse, since a model can then be used in several
different applications, or have more than one view.
• Facilitater or Helper: Classes that maintain little or no state info themselves but assist in
the execution of complex tasks. Ex: To display the card image we may use the services of
a class that handles the drawing of line and text on the display. Another facilitater
will help maintain linked lists of cards. These categories are intended to be representative
of the most uses of classes, and hence useful as a guide in the design phase of object-
oriented programming, but the list is certainly not complete. If a class appears to span
tow or more of these categories, it can often be broken into two or more classes.
Another Set of Class Categories
Tangible Things: easiest classes to discover because they are visible in the problem
domain.
System Interfaces and Devices: easy to discover by considering the system resources
and interactions of the system. Ex: DisplayWindow.
Agents: Sometimes it is helpful to change an operation into an agent class.
For example an InputReader class can be created to separate the operation of getting the
text which is used to construct a message by the Message class. The agent class
decouples the Message class from input mechanisms and separates the abstraction levels
of input processing and controlling message contents.
Events and Transactions: useful to model records of activities that describe what
happened in the past or what needs to be done later. For example, a CustomerArrival
class to specify when where what type of customer is scheduled to arrive. Ex:
MouseEvent
Users and Roles: stand-ins for actual users of the program. For example an
Administrator class is an interface to the human administrator of the system.
Systems: model a subsystem or the overall system being built. Their role are typically
to perform initialization and shutdown and to start the flow of input into the system.
Containers: used to store and retrieve information. Many are implemented using the
standard data structures (lists, queues, … ).
Designing From Scenarios
Designing with CRC cards follows neither the "top-down" nor the "bottomup" models of
software development. Instead, the design might be said to progress from the known to
the unknown. The design process should begin with only the most obvious classes, and
the classes necessary to handle the beginning of an application. The designer(s) then
proceed by playing "what if" - by simulating scenarios that illustrate expected use. The
CRC cards can play a concrete role in this simulation process.

Method Binding
Static binding is where the linker copies the referenced module into the executable image
of the program at compilation/link time. The referenced module becomes a part of the
executable image.
Dynamic binding is where the linker copies only a stub code for the referenced
module into the executable image. That stub code loads the referenced module into
memory at load/run time.
Advantage of static is simplicity. The executable is stand-alone. Disadvantage is
the executable image is larger, and if the referenced module changes, then each
executable that uses it must be relinked. Another disadvantage is that if you have more
than one executable using the module at the same time, you must have multiple copies of
it in memory.
Advantage of dynamic is reduced size of the executable image and that changing
the referenced module does not require relink of the executable. Another advantage is
that most operating systems can share the referenced module, meaning that only one copy
of the referenced module need exist in all of memory for any number of references to that
module, such as from multiple instances of the executable. Disadvantage of dynamic is
that the executable is dependent on the shared library at run time. Another disadvantage
is that, since the module is shared, it must be reentrant and thread safe, and this is not
always done correctly. It helps simplify your application by not having to determine
which type of object you have and which method is appropriate to call.
For example, one of my first OO applications maintained files on different media.
Each class was based on a basic archive class and had the same set of function: generate,
display, print, save, etc. There were derived classes for floppy, tape, CD, hard drive, etc.
From my application point of view I just had to worry about how to create the
initial object because initial input was different for each. But then for the user to
manipulate each of the archive sources my application didn't care. It would just call the
object's display method, the dynamic binding figured out which derived class was
responsible and then called that class' display function. So, all the class would display
their results in a list box. .

Overriding
Method overriding is using same method name along with same number & type of
arguements in base as well as derived class.This is called run time polymorphism asthe
instance i.e object type differntite between the methods.If not done properly then only
base class method will be invoked.so be carefull to bind object with method.
Method overriding is a language feature that allows a subclass to override a specific
implementation of a method that is already provided by one of its super-classes.
Overriding is an important concept in Object Oriented Technology. In today's world
you can't live without overriding. For example in most of the API's used for building
windows based application you always need to override some parent window. Like in
Java you may override methods and data of class Frame, in C++ CMainWnd, in QT
Form etc. In many of your applications that you build using Inheritance you need to
override some members of the parent class.

Let's understand inheritance by an analogous example. Let S be the son of F. There can
be many characteristics that C inherit from his/her father F. Like may be he also loves
listening to music and so does C, F is genius and so is C, F writes poems like C does.
These all are inherited characteristics. But there can be situation like C writes romantic
poems and his/her father used to write tragic poems. Here, C has overridden his/her
father's characteristics of writing a poem. It was inherited from his/her father but he/she
does it differently. The concept of overriding is same in Object Oriented Programming
Languages.

For overriding, there must be inheritance. Once you inherit, you can then override data
member of methods of the parent class. In C++ ":" is used to tell C++ compiler that you
want to inherit something. For example "Class MangoTree : public Tree " means class
MangoTree is inheriting class Tree.
The keyword public adds the information that only the public members are inherited.
Once class MangoTree inherits class Tree, all the public members of class Tree are
accessible from class MangoTree. Like is there is a data member "height" defined in class
"Tree" you can directly use this variable in any method of class "MangoTree". Similar is
the case with methods. But, sometimes you would like to change the implementation of
some of the methods of the parent class. Like though there was a method called,
"getFruitName()", you would write another method of the same name and parameter in
class "MangoTree". The method "getFruitName()" of parent class is not visible in child
class "MangoTree" now. It has its own now. It has overridden the method of its parent.
Similarly, it can also override the data member of its parent. This is what known as
overriding, a popular technique in object oriented paradigm.

A subclass can give its own definition of methods but need to have the same signature as
the method in its super-class. This means that when overriding a method the subclass's
method has to have the same name and parameter list as the super-class's overridden
method.

using System;
public class Complex
{
private int real;
public int Real
{ get { return real; } }

private int imaginary;


public int Imaginary
{ get { return imaginary; } }

public Complex(int real, int imaginary)


{
this.real = real;
this.imaginary = imaginary;
}

public static Complex operator +(Complex c1, Complex c2)


{
return new Complex(c1.Real + c2.Real, c1.Imaginary + c2.Imaginary);
}

public override string ToString()


{
return (String.Format("{0} + {1}i", real, imaginary));
}
}
In above example I have extended the implementation of the sample Complex class given
under operator overloading section. This class has one overridden method named
“ToString”, which override the default implementation of the standard “ToString”
method to support the correct string conversion of a complex number.

Exceptions

Introduction

Stated simply, the exception-handling capability of Java makes it possible for you to:

• Monitor for exceptional conditions within your program


• Transfer control to special exception-handling code (which you design) if an
exceptional condition occurs

The basic concept

This is accomplished using the keywords: try, catch, throw, throws, and finally. The
basic concept is as follows:

• You try to execute the statements contained within a block of code. (A block of
code is a group of one or more statements surrounded by braces.)
• If you detect an exceptional condition within that block, you throw an
exception object of a specific type.
• You catch and process the exception object using code that you have designed.
• You optionally execute a block of code, designated by finally, which needs to
be executed whether or not an exception occurs. (Code in the finally block is
normally used to perform some type of cleanup.)

Exceptions in code written by others


There are also situations where you don't write the code to throw the exception object,
but an exceptional condition that occurs in code written by someone else transfers control
to exception-handling code that you write.

For example, the read method of the InputStream class throws an exception of type
IOException if an exception occurs while the read method is executing. In this case,
you are responsible only for the code in the catch block and optionally for the code in the
finally block.

(This is the reason that you must surround the invocation of System.in.read() with a try
block followed by a catch block, or optionally declare that your method throws an
exception of type IOException.)

Exception hierarchy, an overview

When an exceptional condition causes an exception to be thrown, that exception is


represented by an object instantiated from the class named Throwable or one of its
subclasses.

Here is part of what Sun has to say about the Throwable class:

"The Throwable class is the superclass of all errors and exceptions in the Java language.
Only objects that are instances of this class (or one of its subclasses) are thrown by the
Java Virtual Machine or can be thrown by the Java throw statement. Similarly, only this
class or one of its subclasses can be the argument type in a catch clause."

Sun goes on to say:

"Instances of two subclasses, Error and Exception, are conventionally used to indicate
that exceptional situations have occurred. Typically, these instances are freshly created in
the context of the exceptional situation so as to include relevant information (such as
stack trace data)."

The Error and Exception classes


The virtual machine and many different methods in many different classes throw
exceptions and errors. I will have quite a lot more to say about the classes named Error
and Exception later in this lesson.

Defining your own exception types

You may have concluded from the Sun quotation given above that you can define and
throw exception objects of your own design, and if you did, that is a correct conclusion.
(Your new class must extend Throwable or one of its subclasses.)

The difference between Error and Exception

As mentioned above, the Throwable class has two subclasses:

• Error
• Exception

What is an error?

What is the difference between an Error and an Exception? Paraphrasing David


Flanagan and his excellent series of books entitled Java in a Nutshell, an Error indicates
that a non-recoverable error has occurred that should not be caught. Errors usually cause
the Java virtual machine to display a message and exit.

Sun says the same thing in a slightly different way:

"An Error is a subclass of Throwable that indicates serious problems that a reasonable
application should not try to catch. Most such errors are abnormal conditions."

For example, one of the subclasses of Error is named VirtualMachineError. This error
is "Thrown to indicate that the Java Virtual Machine is broken or has run out of resources
necessary for it to continue operating. "

What is an exception?

Paraphrasing Flanagan again, an Exception indicates an abnormal condition that must be


properly handled to prevent program termination.
Sun explains it this way:

"The class Exception and its subclasses are a form of Throwable that indicates
conditions that a reasonable application might want to catch."

As of JDK 1.4.0, there are more than fifty known subclasses of the Exception class.
Many of these subclasses themselves have numerous subclasses, so there is quite a lot of
material that you need to become familiar with.

The RuntimeException class

One subclass of Exception is the class named RuntimeException As of JDK 1.4.0, this
class has about 30 subclasses, many which are further subclassed. The class named
RuntimeException is a very important class.

Unchecked exceptions

The RuntimeException class, and its subclasses, are important not so much for what
they do, but for what they don't do. I will refer to exceptions instantiated from
RuntimeException and its subclasses as unchecked exceptions.

Basically, an unchecked exception is a type of exception that you can optionally handle,
or ignore. If you elect to ignore the possibility of an unchecked exception, and one
occurs, your program will terminate as a result. If you elect to handle an unchecked
exception and one occurs, the result will depend on the code that you have written to
handle the exception.

Checked exceptions

All exceptions instantiated from the Exception class, or from subclasses of Exception
other than RuntimeException and its subclasses must either be:

• Handled with a try block followed by a catch block, or


• Declared in a throws clause of any method that can throw them

In other words, checked exceptions cannot be ignored when you write the code in your
methods. According to Flanagan, the exception classes in this category represent routine
abnormal conditions that should be anticipated and caught to prevent program
termination.

Checked by the compiler

Your code must anticipate and either handle or declare checked exceptions. Otherwise,
your program won't compile. (These are exception types that are checked by the
compiler.)

Throwable constructors and methods

As mentioned above, all errors and exceptions are subclasses of the Throwable class. As
of JDK 1.4.0, the Throwable class provides four constructors and about a dozen
methods. The four constructors are shown in Figure 1.

Throwable()
Throwable(String message)
Throwable(String message,
Throwable cause)
Throwable(Throwable cause)

Figure 1

The first two constructors have been in Java for a very long time. Basically, these two
constructors allow you to construct an exception object with, or without a String message
encapsulated in the object .

Coping with complexity


- Abstraction mechanisms try to cope with this and object oriented techniques offer
yet another step forward
- A software system may consist of many classes. But in any case, when you have
many, it needs to be managed. Think of a big organization, with its work force
exceeding several thousand employees (let’s take one employee as a one class). In
order to manage such a work force, you need to have proper management policies
in place. Same technique can be applies to manage classes of your software
system as well. In order to manage the classes of a software system, and to reduce
the complexity, the system designers use several techniques, which can be
grouped under four main concepts named Encapsulation, Abstraction, Inheritance,
and Polymorphism. These concepts are the four main gods of OOP world and in
software term, they are called four main Object Oriented Programming (OOP)
Concepts.
- Interconnectedness, the dependence of one portion of code on another portion, is
responsible for this phenomena
- Abstraction is an emphasis on the idea, qualities and properties rather than the
particulars (a suppression of detail). The importance of abstraction is derived from
its ability to hide irrelevant details and from the use of names to reference objects.
Abstraction is essential in the construction of programs. It places the emphasis on
what an object is or does rather than how it is represented or how it works. Thus,
it is the primary means of managing complexity in large programs.
- While abstraction reduces complexity by hiding irrelevant detail, generalization
reduces complexity by replacing multiple entities which perform similar functions
with a single construct. Generalization is the broadening of application to
encompass a larger domain of objects of the same or different type. Programming
languages provide generalization through variables, parameterization, generics
and polymorphism. It places the emphasis on the similarities between objects.
Thus, it helps to manage complexity by collecting individuals into groups and
providing a representative which can be used to specify any individual of the
group.
- Just like abstraction is closely related with generalization, the inheritance is
closely related with specialization. It is important to discuss those two concepts
together with generalization to better understand and to reduce the complexity.

Abstraction mechanism

Abstraction is an emphasis on the idea, qualities and properties rather than the particulars
(a suppression of detail). The importance of abstraction is derived from its ability to hide
irrelevant details and from the use of names to reference objects. Abstraction is essential
in the construction of programs. It places the emphasis on what an object is or does rather
than how it is represented or how it works. Thus, it is the primary means of managing
complexity in large programs.

While abstraction reduces complexity by hiding irrelevant detail, generalization reduces


complexity by replacing multiple entities which perform similar functions with a single
construct. Generalization is the broadening of application to encompass a larger domain
of objects of the same or different type. Programming languages provide generalization
through variables, parameterization, generics and polymorphism. It places the emphasis
on the similarities between objects. Thus, it helps to manage complexity by collecting
individuals into groups and providing a representative which can be used to specify any
individual of the group.

Abstraction and generalization are often used together. Abstracts are generalized through
parameterization to provide greater utility. In parameterization, one or more parts of an
entity are replaced with a name which is new to the entity. The name is used as a
parameter. When the parameterized abstract is invoked, it is invoked with a binding of
the parameter to an argument.

4.11. What is an Abstract class?

Abstract classes, which declared with the abstract keyword, cannot be instantiated. It can
only be used as a super-class for other classes that extend the abstract class. Abstract
class is the concept and implementation gets completed when it is being realized by a
subclass. In addition to this a class can inherit only from one abstract class (but a class
may implement many interfaces) and must override all its abstract methods/ properties
and may override virtual methods/ properties.

Abstract classes are ideal when implementing frameworks. As an example, let’s study the
abstract class named LoggerBase below. Please carefully read the comments as it will
help you to understand the reasoning behind this code.

public abstract class LoggerBase


{
/// <summary>
/// field is private, so it intend to use inside the class only
/// </summary>
private log4net.ILog logger = null;

/// <summary>
/// protected, so it only visible for inherited class
/// </summary>
protected LoggerBase()
{
// The private object is created inside the constructor
logger = log4net.LogManager.GetLogger(this.LogPrefix);
// The additional initialization is done immediately after
log4net.Config.DOMConfigurator.Configure();
}

/// <summary>
/// When you define the property as abstract,
/// it forces the inherited class to override the LogPrefix
/// So, with the help of this technique the log can be made,
/// inside the abstract class itself, irrespective of it origin.
/// If you study carefully you will find a reason for not to have “set” method here.
/// </summary>
protected abstract System.Type LogPrefix
{
get;
}

/// <summary>
/// Simple log method,
/// which is only visible for inherited classes
/// </summary>
/// <param name="message"></param>
protected void LogError(string message)
{
if (this.logger.IsErrorEnabled)
{
this.logger.Error(message);
}
}

/// <summary>
/// Public properties which exposes to inherited class
/// and all other classes that have access to inherited class
/// </summary>
public bool IsThisLogError
{
get
{
return this.logger.IsErrorEnabled;
}
}
}
The idea of having this class as an abstract is to define a framework for exception
logging. This class will allow all subclass to gain access to a common exception logging
module and will facilitate to easily replace the logging library. By the time you define the
LoggerBase, you wouldn’t have an idea about other modules of the system. But you do
have a concept in mind and that is, if a class is going to log an exception, they have to
inherit the LoggerBase. In other word the LoggerBase provide a framework for exception
logging.

Let’s try to understand each line of the above code.

Like any other class, an abstract class can contain fields, hence I used a private field
named logger declare the ILog interface of the famous log4net library. This will allow the
Loggerbase class to control, what to use, for logging, hence, will allow changing the
source logger library easily.
The access modifier of the constructor of the LoggerBase is protected. The public
constructor has no use when the class is of type abstract. The abstract classes are not
allowed to instantiate the class. So I went for the protected constructor.

The abstract property named LogPrefix is an important one. It enforces and guarantees to
have a value for LogPrefix (LogPrefix uses to obtain the detail of the source class, which
the exception has occurred) for every subclass, before they invoke a method to log an
error.

The method named LogError is protected, hence exposed to all subclasses. You are not
allowed or rather you cannot make it public, as any class, without inheriting the
LoggerBase cannot use it meaningfully.

Let’s find out why the property named IsThisLogError is public. It may be important/
useful for other associated classes of an inherited class to know whether the associated
member logs its errors or not.

Apart from these you can also have virtual methods defined in an abstract class. The
virtual method may have its default implementation, where a subclass can override it
when required.

All and all, the important factor here is that all OOP concepts should be used carefully
with reasons, you should be able to logically explain, why you make a property a public
or a field a private or a class an abstract. Additionally, when architecting frameworks, the
OOP concepts can be used to forcefully guide the system to be developed in the way
framework architect’s wanted it to be architected initially.

Das könnte Ihnen auch gefallen