I know about the conceptual use behind creating an abstract class, i.e. defining a common interface for its subclasses where some of the implementation is left to the individual subclasses.
Am I correct in my assumption that there is technically no necessary need for abstract classes, since you can overwrite a superclass method anyway? Were abstract classes just created to make the intention of the classes clearer to the developer?
Example of what I mean:
// Using an abstract class
abstract class Car
{
int fuel;
int getFuel()
{
return this.fuel;
}
abstract String getColor();
}
class RedCar extends Car
{
String getColor()
{
return "red";
}
}
// Without an abstract class
class Car
{
int fuel;
int getFuel()
{
return this.fuel;
}
String getColor()
{
return "defaultColor";
}
class RedCar extends Car
{
String getColor()
{
return "red";
}
}
Were abstract classes just created to make the intention of the classes clearer to the developer?
That's right, but it also prevents developers from doing "silly" things.
For example, you cannot create instances of abstract classes. In the context of your code, it does not make sense to create a "general" Car. You can only create a BlueCar or a RedCar or some other subclass. While instances of an anonymous subclass may seem like instances of an abstract classes, they are in the end constructed from subclasses. If you made the Car class abstracted, however, developers will not accidentally create an instance of Car, because the compiler would complain.
Abstract classes also forces developers to implement the abstract methods. With your non-abstract Car class, I can inherit it and forget that I need to override getColor. Now some other parts of the code might call getColor and gets a nonsensical result "defaultcolor". What the heck is a default color? Making the method abstract forces the subclasses to think about implementing the required methods.
Most people I know avoid abstract classes. From an application programmers point of view, my opinion is that abstract classes should be avoided. Using interfaces are so much more flexible not forcing your work to adhere to a class hierarchy.
a bit formally: an abstract class is strict inheritance, while interfaces are composition.
An example where abstract classes are useful is when making class libraries. The hierarchy that abstract classes enforces, can make the library more easily understandable for application programmers. However, I do believe this comes at the cost of longer development times of the library.
Related
In context of Java, could a class replace the need of extending an abstract class by extending another non-abstract class and implementing an interface together, both of which combined have all the methods(abstract and implemented), of an abstract class?
In context of Java, could a class replace the need of extending an
abstract class by extending another non-abstract class and
implementing an interface together, both of which combined have all
the methods(abstract and implemented), of an abstract class?
Can it? Yes
Should it? No
An abstract class can be replaced by a concrete one, but you will be altering your system.
Do remember: an abstract class can not be instantiated, nor should it be, since it's not 'concrete enough' to make sense for your business. (If it does, it shouldn't have been an abstract class to begin with)
If you make it concrete, you risk that developers will use instances of the (what-should-be) abstract class.
If you change it the way you propose:
public void doSomething(MyAbstractClass instance){
// here we know there is an implementation provided by a subclass
}
would become
public void doSomething(MyShouldBeAbstractClass instance){
// here they can pass instances of the base class, which might have unsupported methods
}
For instance:
public String getConcreteInformation(){
throw new UnsupportedOperationException("Should be called on a child class");
}
and could lead to a lot of nasty bugs
Is this a valid abstract class?
I know that abstract classes cannot be instantiated, so I'm suspicious of the instance variable language and constructor Programmer. It also implements a writeCode method that is not declared as default. If I recall correctly, the only methods that can be implemented in an abstract class are those with default implementations.
public abstract class Programmer {
private String language;
public Programmer (String language) {
this.language = language;
}
public void writeCode() {
System.out.println("Written in " + language);
}
}
If it is a valid abstract class, can someone explain why it contains a constructor?
Also, more broadly speaking, can abstract classes have instance variables? If so, why? Doesn't that seem counter to the idea that abstract classes cannot be instantiated?
Finally, I would love it if someone addresses the writeCode method. Why is it implemented, without a default modifier?
Thanks!
Yes, this is a valid abstract class.
Abstract classes can have constructors, instance variables and concrete methods.
The main difference with regular classes is that they can also declare abstract methods, delegating implementation to the non-abstract child classes (this is not the case here, you have no abstract methods).
Another difference is that they cannot be initialized directly, even if they do provide an accessible constructor.
The constructor(s) of an abstract class are typically used to initialize values internally, and to invoke from child classes or anonymously.
See documentation here.
Example
Given...
public abstract class Programmer {
private String language;
public Programmer(String language) {
this.language = language;
}
public void writeCode() {
System.out.println("Written in " + language);
}
}
... and...
public class JavaProgrammer extends Programmer {
public JavaProgrammer() {
super("Java");
}
}
Concrete child class
new JavaProgrammer().writeCode(); // prints "Java"
Anonymous class (note the empty class body {})
new Programmer("JavaScript"){}.writeCode(); // prints "JavaScript"
As you say, abstract classes cannot be instantiated. However, when a subclass of any abstract class is created, the first sentence in its constructor is a call to super(), which is nothing but a representation of the constructor of its parent class, the abstract class.
An abstract class can have instance variables and methods. It is even possible to have an abstract class without any abstract method. However, an abstract method can only be declared in an abstract class.
You are mixing abstract classes and interfaces concepts. An interface cannot have instance variables, and any implemented method must be prefixed with the static or default modifier.
This is correct example of abstract class. Answering your questions:
default keyword is used (as of java 8) in interfaces, where you can implement default method implementation, abstract class can have a method implementation just as any normal java class
having constructor in abstract class imposes having a constructor in extending class so that the underlying abstract class can be properly constructed (e.g. fields instantiated etc)
abstract class cannot be instantiated but as any other class can have private fields and internally make use of them, should they be protected then extending classes will also be able to directly access them.
It seems to me you're confusing abstract class with interface.
The abstract class contains a constructor because when the instantiated class based on the abstract class is created it will call super() to execute the code from the abstract class.
The instance variable is a similar thing. The class that is developed from the abstract class would then have access to the language and be able to work with it.
In terms of the default, that would be best practice but there is no absolute requirement for it to be there.
Abstract classes are partial implementations. Sometimes, as in the case above, the only thing that prevents the class from being instantiated is the abstract modifier itself!
If an abstract class has constructors then it means that subclasses must invoke one of the constructors (by calling super(...) in their constructor.
More broadly it seems that you're confusing Interfaces and Abstract Classes. Interfaces are a contract, they specify how a class should behave but provide no implementation whatsoever. Abstract Classes are a specific partial implementation of some code.
Interfaces are used (broadly) when you require someone else to provide behaviour but you don't care how it works. Abstract Classes are used when you want to assist people in providing behaviour, but you still require them to provide some details.
Since these definitions overlap, it's not unusual to see both Abstract Classes and Interfaces provided, e.g. the various Adapters in java.swing.*.
I want to declare a couple of abstract methods (so the implementation is required in the classes that inherit from this one) to fit my situation, which is:
I am making a puzzles solver program. So far I have 3 packages:
games.puzzles
games.puzzles.rivercrossing
games.puzzles.rivercrossing.wolfgoatcabbage
I don't want to get too specific but in the games.puzzles.rivercrossing package I have two classes that represent a bank and a state: GenericBank and GenericState.
Now, they define some behavior, but there are some methods that the classes that inherit from these must have, like move() to move one element from one bank to the other or isPermitted() and isFinal() to check the states.
For example, in the last package I have the WolfGoatCabbageGame class and it must have its own Bank and State classes which will inherit from the generic ones. These particular Bank and State classes must implement the methods I mentioned above, for example in the Wolf, Goat and Cabbage game, to check if the goat and the wolf are not in the same bank, etc.
So initially I declared the generic classes as abstract, and these methods to be implemented abstract as well:
public abstract class GenericBank {
// more members ...
public abstract boolean move(Element element, GenericBank dst);
// more members...
}
public abstract class GenericState {
// more members...
public abstract boolean isPermitted(GenericBank bank);
public abstract boolean isFinal(GenericBank bank);
// more members...
}
And this looked like it'd work until I found out I had to instantiate GenericBank and GenericState objects, which of course can't be done if these classes are abstract.
So I had to remove the abstract qualifier from the classes.
So... what can I do? How can I declare abstract methods (or achieve the same behavior) in a non-abstract class?
How to declare abstract method in non-abstract class?
Answer: You can't. It's kind of the definition of abstract. It's the same reason you can't instantiate an object as an abstract class.
Either:
A) You need to use Interfaces
B) Leave the methods empty in the parent class:
//technically this needs to return a value, but it doesn't need to *do* anything
public boolean isPermitted(GenericBank bank){ return false; }
C) Refactor your code so that you aren't instantiating abstract objects. I cannot advise how to do this as you haven't provided any code regarding this.
You could replace the abstract methods with empty methods that do nothing and return the default value of their respective return type (and, if necessary, make it part of the generic classes contract, that subclasses must override these methods).
Alternatively, you could keep your abstract Generic*-classes and add Null*-classes with abovementioned empty implementations, following the Null object pattern.
You cannot declare abstract methods in a non-abstract class, final dot.
That would simply defile the concept of abstract methods.
What you can do is have your class hierarchy implement interfaces dictating the required methods to implement.
If you found your formerly abstract classes were actually better designed as concrete classes, do convert them to concrete classes and implement the methods, even with a default, general implementation.
You can then fine-tune the overrides in your child classes.
Remove the abstract qualifier and add a empty body, or throwing some runtime exception.
Or instantiate these generic classes as anonymous sub classes
You cannot, the very definition of an abstract class is that it has abstract methods.
What you can do, is define default behaviour, that can be overruled by subclasses.
However, I would carefully consider your class hierarchy before doing this. The fact that you need to instantiate some classes before their actual implementations are known, suggests that your design may need re-thinking.
If you're going to re-design, you will want to look at the time of instantiation - and underlying that, the reasons for instantiating.
Right now, you want to use some of the common behaviour of a class, before the actual instance of that class is known.
It goes a bit beyond the scope of answering the question, but: consider explaining the design of the code to a friend. Or to a rubber duck. This may help you to find a fresh approach.
You can use Virtual instead!
internal class ClassA
{
public void Print()
{
Console.WriteLine("A");
PrintVirtual();
Console.WriteLine("--------------------------------------------------");
}
protected virtual void PrintVirtual()
{
Console.WriteLine("Virtual");
}
}
internal class ClassB : ClassA
{
protected override void PrintVirtual()
{
Console.WriteLine("B");
}
}
internal class ClassC : ClassA
{
protected override void PrintVirtual()
{
Console.WriteLine("C");
base.PrintVirtual();
}
}
and you can run the test
new ClassA().Print();
new ClassB().Print();
new ClassC().Print();
I am learning JAVA and following the book JAVA:The Complete Reference by Herbert Shildt.
I learned about abstract classes in Java, but could not understand reason behind this line:
An abstract class cannot be directly instantiated with new operator.
I searched over web and stackoverflow and followed these questions: Why can't we instantiate a abstract class in JAVA? and Why can't we instantiate an interface or an abstract class in java without an anonymous class method?
In one answer, someone wrote as:
Simply, in a good object oriented program, you should never want to
instantiate an abstract class or interface. If you do, the design is
probably wrong.
I do not understand why it is important not to instantiate an abstract class for good OOP design. If someone can give a good explanation, then please help.
An abstract class should be something that doesn't make sense if it exists completely on its own.
Take a Vehicle for example. Can you describe a Vehicle without describing a specific type of Vehicle at the same time? No - because Vehicle is just a way of describing common features and behaviours of a group of related objects. Alternatively, you could think of them as concepts.
Your quote:
Simply, in a good object oriented program, you should never want to instantiate an abstract class or interface. If you do, the design is probably wrong.
Is spot on. If you've written an abstract class that you want to instantiate completely on its own, then it isn't an abstract class. If you ever find yourself in this situation, you probably need to carry out another level of abstraction to separate out the abstract parts from the bits that actually start to condense the class into something concrete. The only thing you should want to do with an abstract class is to extend it - to turn it into something less vague (or more concrete if you prefer).
Of course, Java can seem a little contradictory at times. In fact, writing a constructor for an abstract class is perfectly valid:
abstract class Vehicle {
// You might have some common variables defined here
Vehicle() { }
}
At first this seems a little stupid. Why can I write a constructor, which is designed to allow you to instantiate an object, when I'm not allowed to instantiate the class? The compiler will even create a default constructor for you if you don't write one!
The answer there is that you are allowed to instantiate an abstract class - you're just not allowed to instantiate it directly using the new keyword. But the most important part of abstract classes is that they're designed to be extended.
When you instantiate a subclass of an abstract class, you either explicitly or implicitly call super(); inside the constructor:
public class Car extends Vehicle {
public Car() {
super(); // If you don't put this here, the compiler will!
}
}
This actually makes sense when you think about it - you can't have a Vehicle on it's own, but my car that's sat in the car park is definitely a Vehicle. Once I have a concrete extension to my concept of a Vehicle, Car in this case, then I can have a Vehicle.
Probably the most useful thing that this enables you to do is create generic collections. Because Vehicle is the superclass of all of the different types of Vehicle, I can say:
List<Vehicle> vehicles = new ArrayList<>();
Or if you prefer not to/can't use the diamond operator (<>):
List<Vehicle> vehicles = new ArrayList<Vehicle>();
This allows me to put any type of Vehicle into that collection:
vehicles.add(new Car());
vehicles.add(new Van());
vehicles.add(new Lorry());
vehicles.add(new Motorcycle());
// and so on...
Although there are many other advantages to this, too numerous to cover in this answer.
You can't instantiate an abstract class, bacause it usually contains abstract methods, which have no implementation. In order to instantiate a class, all of its methods must be implemented. Sub classes would implement the abstract methods, and you would instantiate those sub classes.
However, even if you implement all the methods, you would sometimes define the class as abstract if you want to prevent users of the class from instantiating it. You would define a class as abstract if it is meant to be sub-classed, and doesn't contain all that is required for creating a fully functional object.
As for interfaces, they just declare methods without implementation (with the exception of default methods introduced in Java8), and don't have constructors or class variables. You can't instantiate them without implementing all of their methods.
Well, let's take an example so that you can understand why in object oriented paradigm the abstract classes are not for instantiation, but for extending :
Suppose that we want to design a Zoo Application , where we present each animal by a set of information, but each type would be presented by it's class, if we want to follow a good practice, then we create a class called Animal where we put commons information about all animal ( id, price, entryDate...).
public abstract class Animal {
private long id;
private Date entryDate;
private double price;
private String name;
// other common info
}
This would help designing other classes from a structural point of view
public Lion extend Animal {
private boolean isFromAfrica;
}
Abstract classes are meant to provide a skeleton structure so there is no concrete implementation in them.
The child classes are expected to fill in the implementation and hence they can be instantiated.
Yout answer is in your given statement:
Simply, in a good object oriented program, you should never want to instantiate an abstract class or interface. If you do, the design is probably wrong.
You should never want to instantiate an abstract class.Because abstract class is an uncomplete class whose intstantiation does not make any sense.You define a behavior for classes which will extend your abstact class. It's more about a guy saying "these classes should look like that, and they got that in common, so fill in the blanks!".
Abstract classes are useful when you need a class for the purpose of
inheritance and polymorphism, but it makes no sense to instantiate the
class itself, only its subclasses. They are commonly used when you
want to define a template for a group of subclasses that share some
common implementation code, but you also want to guarantee that the
objects of the superclass cannot be created.
So it is to important to do not instantiate an abstract class as according to right design, purpose of abstract class is different,you use it when used when you want to define a template for a group of subclasses and it makes no sense to instantiate the class itself,
For example: let's say you need to create Dog, Cat, Hamster and Fish objects. They possess similar properties like color, size, and number of legs as well as behavior so you create an Animal superclass. However, what color is an Animal? How many legs does an Animal object have? In this case, it doesn't make much sense to instantiate an object of type Animal but rather only its subclasses.
it may seem baffling at first , but you will get used to it
well technically it can't be instantiated because -
it does not contain method definitions.so y waste space on its instantiation!
theoretically-
it defeats the entire purpose of abstract class if u can instantiate it..y go thru all the trouble of creating the concept when it is no different than the ordinary class
Abstract classes sole purpose is to be extended. The abstract class will contain common code for all its subclasses and the subclasses will only implement those sections that is relevant to it.
Abstract classes are quite useful for the Command pattern. For example, let's say you have a task that needs to execute a set of actions, then you can define a Command abstract class:
public abstract class Command
public void doCommand() {
// Actual code here doing stuff...
runInternal();
// more code;
}
public abstract void runInternal();
}
The idea now is that you can implement a whole range of commands, for example:
public void RedCommand extends Command {
public void runInternal() {
// Real code that does red things
}
}
...and also
public void BlueCommand extends Command {
public void runInternal() {
// Real code that does blue things
}
}
Now, you can have something like this:
List<Command> list = new ArrayList<>();
list.add(new RedCommand())
list.add(new RedCommand())
list.add(new BlueCommand())
for(Command c : list) {
c.doCommand();
}
Now it's easy to add more commands later, by simply extending the Command abstract class and implementing the runInternal() method. As with all things, this pattern can/is heavily abused, but in the right environment is makes for easy/readable code.
The reason is that sometimes several concrete classes (classes that can be instantiated) all share common functionality. The common functionality can be shared through inheritance. The common methods are put in the abstract classes. The concrete subclasses can use those methods as they are defined in the abstract class, or concrete subclasses can override the methods to implement special behavior.
As analogy, think of these four things: animal, mammal, human, elephant. There are real creatures called "human" and "elephant", but there are no creatures named "animal" or "mammal". Human and elephants are concrete that way. Animals and mammals are abstractions we created to describe traits common to different creatures. Humans and elephants are kinds of mammals. Mammals are kinds of animals.
In the OO world, we could model these four things as classes. Class Mammal is an abstract class that extends the abstract class Animal. Human and Elephant are concrete classes that extend Mammal. Declaring classes Animal and Mammal as abstract tells others that there is no such thing as an "animal" or "mammal" running around in the woods. Animal and mammal are just ideas we invented to describe things that humans, elephants, and other creatures have in common.
Why do we declare a class as abstract? I know it cannot be instantiated, but why give a special keyword for it. Even a 'normal' class will work just as well and can be easily subclassed. so what is the main advantage of making a class abstract?
In abstract class you can implement some method and can make some abstract all your client will have to implement it also. you can provide some common functionality , also you can have some inherited fields and some of the skeleton method here
An abstract class can have abstract methods and "concrete" methods.
The "concrete" methods can use the abstract methods, and can be sure that they are (correct) impelmented at runtime. Because every (not abstract) subclass has to implement them. (And ther will be no instance of the abstract class itselfe).
So it is all about savety! - It makes sure that the programmer who want to subclass an abstract class must implement the abstract method(s).
If you do this only with a normal class then the class, corresponding to the abstract class, would have the (abstract) methods with an empty Implementation, and only a notic to the programmer that he has to override this method.
Of course you can use the concept of abstract classes for other thinks, like create not instanciable classes, but that is not the main point.
I think you misunderstand the point of abstract classes: they provide a partial implementation of some functionality, but not a complete implementation.
You suggested that abstract classes were redundant because you can define incomplete methods using public void methodname(){} -- which is certainly ok. However, let's say your clients inherit from a class defined in such a way, how do they know which methods to override? What happens if they forget to override a method? Now their derived class has an incomplete definition -- you don't want that.
The abstract keyword forces clients to provide implementations for certain methods, otherwise the code won't even compile. In other words, it provides a compile-time guarantee that classes you use or create are fully implemented.
Declaring the class abstract prevents any code from instantiating the class.
This enforces the design guideline to make non-leaf classes abstract.
It allows you to add abstract methods to your superclass (and implementations to the subclasses) later, without affecting any existing clients.
The abstract keyword works even if the non-leaf class does not currently have any abstract methods.
Just a real life example. I have a GUI abstract class that is the parent for all my GUI components. Lets call this AbstractSuperClass. Each of my components that extend AbstractSuperClass need their own implementation of the save function. So the nice thing about making my super class abstract is that I can have an array of type AbstractSuperClass that can hold all of my GUI components. I can then loop over that array and call the save function knowing that each GUI component has its own save method. Since the class is abstract, it forces my subclasses to provide a implementation of the save function.
This is especially useful because when we open up our APIto other programmers, they dont get the source. They just extend the AbstractSuperClass and must provide a save implementation.
It's useful if you want to have a group of classes that inherit the same logical functions.
But in the same time, the class only implements the basic logic, and doesn't contain any real functionality.
You should see it as a skeleton class.
For example, I once made a class with these specifications :
Controls the process of executing a command on another thread, and relays events of that process.
The class itself didn't have any functionality by itself (didn't implement the actual work() function)
So the result is an abstract class, that can be inherited, that already has a built in thread control, which all you need to do is just implement the work() method.
If your class has some default behavior and you want some other behavior to be implemented by the extending classes then you use abstract classes. They cannot be initialized, you can think of abstract classes as a template for the extending classes.
Abstract classes can also call the abstract methods which in result calls extending object's method. Anyways there are lot's of discussions about when to use abstract classes, when to prefer it over an interface. Make a google search, it is an epic discussion :) interfaces vs abstract classes.
You would declare a class as abstract if it makes little to no sense to create an instance of it (you would create instances of subclasses).
public abstract class Shape {
public double calculateArea();
}
public class Square : Shape {
private double side;
double calculateArea() {
return side*side;
}
}
public class Circle: Shape {
private double radius;
double calculateArea() {
return 3.1415 * radius * radius;
}
}
public class MainClass() {
public static void Main() {
Shape myShape = new Square();
system.out.print(myShape.calculateArea());
myShape = new Circle();
}
}
It makes no sense to create an instance of Shape because it doesn't mean anything concrete, its an abstract concept. However, you can have variable of type Shape which allows you to program around the common base-type (though it could be argued that an interface might be better in this situation).
Generally, if there is inheritance, as in a super domain class, with common methods and common implementations in subclasses then look into going with an abstract class, which is not that often, but I do use it.
If you just go with Abstract classes just because there is inheritance, you can run into problems if the code changes a lot. This is detailed very well in the example here: Interfaces vs Abstract Classes in Java, for the different types of domain objects of motors. One of them required a dual powered motor, instead of a specific single type, like asolar powered or battery powered motor. This required multiple subclass implementation methods from both motor types to be used in a single subclass and that is where abstract classes can get messy.
To sum it all up, as a rule you want to define behaviors (what the objects will do) with interfaces and not in Abstract classes. In my thinking, the main advantage for Abstract classes is when the focus from the use case is on an implementation hierarchy and code reuse from subclasses.