When I learned about abstract classes is said WT(H*)!!!
QUESTIONS:
- What is the point of creating a class that can't be instantiated?
- Why would anybody want such a class?
- What is the situation in which abstract classes become NECESSARY?
**if you know what i mean*
- most commonly to serve as a base-class or interface (some languages have a separate
interface
construct, some don't) - it doesn't know the implementation (that is to be provided by the subclasses / implementing classes) - abstraction and re-use
- when the base-class can provide no meaningful default-implementation for a method (but allowing subclasses to re-use the non-abstract parts of the implementation; any fields, non-abstract methods, etc)
For example:
public abstract class Stream { /* lots of code, some abstract methods */ }
What the heck is a stream by itself? What kind of stream? a stream to a file? a network? a memory buffer? Each may have different and unrelated ways of reading / writing, but provide a common API. It makes no sense to create just a Stream
, but via the abstract
class, you can code to the Stream
API without knowing the details:
Stream s = CreateStream(...); // I don't *care* what kind of stream
s.Write(new byte[] {1,2,3,4,5});
s.Close();
Abstract (Base) classes give you semi-concrete classes to implement your class hierarchy against. They allow you to do several things:
- Consolidate common behavior (unlike an interface which only defines the contract)
- Provide default (and optionally override-able) implementations for functions
- Provide well defined branch points for inheritance hierarchies
- Control IoC injection points
The list goes on.
An abstract class is one that cannot be instantiated. For example, a Square, Circle, or Rectangle is a type of shape and could be derived from a class Shape.
A Shape will contain code that is common to a Square, Circle, or Rectangle such as calculating the area of the shape. But instantiating a Shape would be useless since it's an abstract concept and squares, circles, and rectangles are real entities.
1) What is the point of creating a class that can'y be instantiated?
Just because something is not instantiated directly does not mean it is useful. An abstract class plays an important role in inheritance and can be very useful in class design of its inherited classes.
For instance, I have used abstract classes before to define the basic structure of what a class must conform to. Then I have defined inherited classes based on that abstract class and if I have missed a required method or something, it can be picked up by the compiler.
What this also allows you to do is associate inherited classes together which means you can then assume certain methods defined in the abstract class will exist in the inherited classes - which can be useful.
2) Why would anybody want such a class
Typically I use it for ensuring that a series of inherited classes have certain methods etc. For me it is really useful for design of a structure of a set of inherited classes.
3) What is the situation in which abstract classes become necessary?
I don't think an abstract class is ever necessary, but when used in certain circumstances it can be useful and help to simplify the problem you are solving.
The point is to specify methods that derived classes must implement, same as an interface, but also provide some of the implementation (which an interface cannot do). Abstract classes are never, strictly speaking, "necessary" - but they are useful. Just search the .NET or Java standard library for them and see for yourself how they are used. You will find there are plenty of examples.
Abstract classes are only useful if you use inheritance. You create subclasses that must implement the same interface as your abstract class and will inherit some base implementation you may have defined in your abstract class.
Its simply to Hide the actual implementation from the client who consumes it.
- It Provides the concerete implementation for the certain functionality and this cannot be directly instantiated
- This will only be accessed from the classes those are implementing it.
- So the clients consuming the derived class, will never know the implementation of the functionality because its abstratced.
Now you would ask why do we need this, since the interfaces serve the same mechanismm.. Go through the simple logger example
interface ILogger
{
string PrepareLog(System.Exception ex);
void InitializeLogger(string Type);
int WriteLog(string msg);
}
Any logging client implements this interface should implement all this functionality
class EventLogger : ILogger
{
public override void InitializeLogger(string Type)
{
//Event Logger Initialize
}
public override int WriteLog(string msg)
{
//Write to event log
return 1;
}
public override string PrepareLog(System.Exception ex)
{
return ex.StackTrace ;
}
}
class FileLogger : ILogger
{
public override void InitializeLogger(string Type)
{
}
public override int WriteLog(string msg)
{
//Write to File
return 1;
}
public override string PrepareLog(System.Exception ex)
{
return ex.StackTrace ;
}
}
class MailLogger : ILogger
{
public override void InitializeLogger(string Type)
{
}
public override int WriteLog(string msg)
{
//Write to mail
return 1;
}
public override string PrepareLog(System.Exception ex)
{
//prepare HTML Formatted msg
return ex.StackTrace ;
}
}
And the classes EventLogger ,FileLogger and maillogger implements the iLogger and gives the Context Specific implementation. Now we wanted to hide the actual implementation of PrepareLog and this would do the common operation of preparing the log message from the exception object.
In our current implementation we dont have the option to make the single method concrete and others to be just contracts.
so lets change the implementation little bit with abstract classes
abstract class AbstractLogger:ILogger
{
#region ILogger Members
public virtual string PrepareLog(System.Exception ex)
{
return ex.StackTrace;
}
public abstract void InitializeLogger(string Type);
public abstract int WriteLog(string msg);
#endregion
}
class EventLogger : AbstractLogger
{
public override void InitializeLogger(string Type)
{
//Event Logger Initialize
}
public override int WriteLog(string msg)
{
//Write to event log
return 1;
}
}
class FileLogger : AbstractLogger
{
public override void InitializeLogger(string Type)
{
}
public override int WriteLog(string msg)
{
//Write to File
return 1;
}
}
class DBLogger : AbstractLogger
{
public override void InitializeLogger(string Type)
{
}
public override int WriteLog(string msg)
{
//Write to DB
return 1;
}
}
class MailLogger : AbstractLogger
{
public override void InitializeLogger(string Type)
{
}
public override int WriteLog(string msg)
{
//Write to mail
return 1;
}
public override string PrepareLog(System.Exception ex)
{
//prepare HTML Formatted msg
return ex.StackTrace ;
}
}
Now i have created the AbstractLogger class which inherits from the iLogger and implemented the PrepareLog method alone, remainig methods left abstract. so the consumers will write the context specific code in their implementation.
So now the PrepareLog method completely hidden (meaning the log preparation) from the cosumers initialized any of the Loggers.
then why PrepareLog is Virtual ed??
There are scenarios the consumer may want to override the preparelog method, Ex: MailLogger will override the PrepareLog and format HTML formatted output to supply to mail messages.
An abstract class is an abstraction. It guarantees behaviors exist but does not force how the behavior is implemented. This leaves you free to change the way the behavior is implemented, if you later decide you want to.
An abstraction is like a keyboard, monitor, or cell phone. All keyboards have the ability to enter data; all monitors have the ability to display pixels; and all cell phones have the ability to make calls. But the manufacturers of these items have different ways of implementing the behavior.
So when you want to make a call, you can do it from pretty much any cell phone because all cell phone manufacturers create phones that adhere to the common abstract idea of what a cell phone is. You don't need to relearn how to make a call on a Samsung if you have already learned how to do it on a BlackBerry or LG.
A cell phone is a cell phone, and subclasses of an abstract class are all the abstract class.
The point of an abstract class is to define (restrict) your interface, without describing the implementation.
An abstract class can be instantiated by constructing a compatible object with a derived class type.
To implement a clean interface that hides ugly platform specific code. Also to hide privates from any sort of exposure. (So that you are truly forced to use the class with the abstracted interface.)
It is necessary when you have two different implementations of the same class that are radically different. Think of a file, a socket, and a block of memory. All of them can make readable data available -- using an abstract class you can implement those three in the three different ways, even though the using code (the call-sites) is written one way to support all three.
Both interfaces and abstract classes promote loose coupling in your code base. Abstract classes are a compromise between interfaces and concrete classes, because abstract classes can have actual methods with implemented behavior.
In general, prefer interfaces. Abstract classes are useful when you have an inheritance tree that has common operations to be used by the child classes. But even here you may want to declare that your abstract class implements an interface. Josh Bloch calls this the "Abstract Interface" pattern. This allows you to deploy different implementations of even the abstract class, which paradoxically isn't actually completely abstract -- only interfaces are.
Same as with interfaces, an abstract class is a contract in which you have provided some general (or abstract) functionality that is applicable to many scenarios, but expect an implementer to provide some functionality that is specific and/or different for each scenario. Someone mentioned the Stream
example - very good example.
Okay, now you made an interface with all the methods that change in each implementation. As you program, you notice that some code blocks are shared by ALL implementations of the interface.
These code blocks should go in an abstract class, instead of being repeated in every implementation. That way, when something changes, you only fix the code in the abstract class instead of in every implementation.
It's only abstract because you want all the inheriting classes to have their own implementations.
Abstract classes serve an useful purpose by being able to create a class that embodies a concept rather than something concrete. E.g, Animal can be a class, but no one just an animal, it is either a Bird, Dog, or Cat etc which are different kinds of animals. Hope this helps. It also goes in conjunction with concepts like inheritance and polymorphism.
精彩评论