We all know abstract modifier in a class makes it
non-instantiable,
candidate for abstract methods,
Non final, non static, non private
In addition to that I would like to know exactly all the changes or side-effects it represents behind. One cannot ask what he/she does not now yet, but I'd like to know whether is something more to consider in terms of inheriting, constructors etc.
Aside from the two official points described, is there any difference or special behavior between an abstract class and a concrete one to be considered when extending, calling super.
Does the compiler assume it is a regular class and has the properties as such for everything other than disallowing instantiation?
Abstract class is, for the most part, a design concept. It does more for the readers of your code than it does for the compiler. The compiler and JVM support required for them is minimal: it boils down to setting a "do not instantiate me" flag on the class, and checking it when compiling the code and when trying to create an instance through reflection.
Benefits to human readers of your code, on the other hand, are much bigger: they know that you designed your abstract class for inheritance, and see what extension points you made for them through abstract methods. In addition, the compiler will track for them if they have provided overrides for all abstract methods.
Related
I have the main abstract class that is a base for bunch of classes. Some of them does not need all the fields and methods from the main abstract class, so I have created second abstract class and splitted main abstract class into two parts. The main abstract class contains, for example, a, x fields and their getters/setters, the second abstract class inherits from the main and contains additional b, c fields and their getter/setters. There are simple classes that are inheriting from the main class,and more complicated are inheriting from the second class. I want to create objects of each class as instances of the main class. Is it right way to do that? I have to type check and cast when I want to use methods from the second abstract class. It makes my code complicated. How can I solve this problem?
MainAbstractClass ---> SecondAbstractClass ---> MyComplicatedClasses
|
|
V
MySimpleClasses
One of the OO principles is Favor composition over inheritance.
This means that common behavior is not provided through base classes but via Component classes which are passed in via dependency injection (preferably as constructor parameters.
The answer depends on your actual needs.
You can instead choose to store the extended abstract class specific fields in a class that does not implement your base class and make it a member of more complicated classes.
You can choose to keep everything in a single base class and nothing forces you to use all the fields of an interface in every class that implemented your interface.
You can also keep using your approach but since you store the classes as an instance of the base class, it will be hard to read.
I believe that if you think code does not look very good, it is probably not good. However, there is usually no single answer to this kind of design questions and the best solution is relative to your preferences.
I think this need of type cast is a smell of fragile design. Here when we assume MyComplicatedClass ISA KIND OF MainAbstractClass as shown by TJ Crowder then object must behave as MainAbstractClass (meaning it can honor only API of MainAbstractClass). If it expects special treatment as MyComplicatedClass its false commitment and will need Casting. Such casting (by identifying type) goes against OO principles and kills polymorphism. Later this will end up in Ladder of InstanceOf and type casts as in the scenarios rightly pointed out by T.J. Crowder.
I would suggest readdress the design. e.g. though our all user defined type instances ARE KIND OF Object, but we use Object API only for methods defined in Object class. We do not use Object o = new MyClass(). There are occasions in frameworks or like Object.equals() method where type cast is needed as API is defined before even concrete extension is written. But it is not a good idea for such simple complete (without open hooks for extensions) Hierarchies.
I've been wondering what is the difference between them? Is it only in this: abstract class declares what an object is and interface says what object can do? Or there is something more deeper? Thanks.
Whether it can have fields, whether it can have a constructor, whether any of those methods can be protected/package-private/private, whether subtypes can inherit from other abstract classes/interfaces...that about covers it.
The statement "abstract class declares what an object is" refers to the rule that says that a class may inherit from a base class if it has an "is a" relationship to the base class. So, a Sedan may inherit from Car because a Sedan "is a" Car. But that's only part of the story. Usually, we define abstract base classes to inherit from when we want the abstract base class to contain some functionality that restricts derived classes in what they can do, often by exposing final methods which cannot be overridden. So, a hypothetical mail delivery abstract base class may offer a public final prepareAndSend() method which invokes abstract overridables on itself called stuffEnvelope(), lickEnvelope(), mailEnvelope(), in that order. The derived class may override those methods, but it has no power to change the order in which they will be invoked because prepareAndSend() is final. You can't impose such restrictions with interfaces.
Interfaces, on the other hand, describe "capabilities" or "aspects" that an object may have. An object may have many different capabilities, so it may implement many interfaces.
Note that it may seem that the "is a" relationship can apply to interfaces, but it either only happens in certain contrived examples, or it is an illusion caused by the liberal syntax of the English language; it is not generalizable, in many cases it is not even factual, and that's the reason why there is no rule that says that an object should have an "is a" relationship with each interface that it implements.
So, someone may of course make an "ICar" interface, there is nothing wrong with that, in which case there will inevitably be something that "is a Car", but what you are more likely to see is interfaces like "IDrivable", "IInsurable", "ITaxable", "IFuelConsumer", etc. all of which describe traits. The fact that you can then say "a car is a taxable" is a fluke of the English language; a car does not actually bear an "is a" relationship with "taxable" because "taxable" is not even a thing. So then, whoever came up with that "ICar" usually just meant it as a convenience to combine all the characteristics of a car into one common interface.
In Java, there are no pure abstract classes. A class that declares only abstract methods has concrete methods also, because it is a subclass -- directly or indirectly -- of the concrete Object class.
An interface is a better choice for defining an abstract API. Java allows classes to extend at most one class, but implement multiple interfaces.
From the Java tutorial Abstract Methods and Classes (line breaks added):
However, with abstract classes, you can declare fields that are not static and final, and define public, protected, and private concrete methods.
With interfaces, all fields are automatically public, static, and final, and all methods that you declare or define (as default methods) are public.
In addition, you can extend only one class, whether or not it is abstract, whereas you can implement any number of interfaces.
The tutorial also recommends cases when an abstract class or interface are desirable. Paraphrased, it recommends abstract classes when you want to share code or non-static, non-final fields, or use access qualifiers other than public. Usually none of these will apply to a pure abstract class.
It recommends interfaces when you want to specify an API that may be implemented by multiple unrelated classes, or want to take advantage of multiple inheritance of interface types.
By making private constructor, we can avoid instantiating class from anywhere outside. and by making class final, no other class can extend it. Why is it necessary for Util class to have private constructor and final class ?
This is not a mandate from a functional point of view or java complication or runtime. However, it's a coding standard accepted by the wider community. Even most static code review tools, like checkstyle, check that such classes have this convention followed.
Why this convention is followed is already explained in other answers and even OP covered that, but I'd like to explain it a little further.
Mostly utility classes are a collection of methods/functions which are independent of an object instance. Those are kind of like aggregate functions as they depend only on parameters for return values and are not associated with class variables of the utility class. So, these functions/methods are mostly kept static. As a result, utility classes are, ideally, classes with only static methods. Therefore, any programmer calling these methods doesn't need to instantiate the class. However, some robo-coders (maybe with less experience or interest) will tend to create the object as they believe they need to before calling its method. To avoid that, we have 3 options:
Keep educating people to not instantiate it. (No sane person can keep doing it.)
Mark the utility class as abstract: Now robo-coders will not create the object. However, reviewers and the wider java community will argue that marking the class as abstract means you want someone to extend it. So, this is also not a good option.
Private constructor: Not protected because it'll allow a child class to instantiate the object.
Now, if someone wants to add a new method for some functionality to the utility class, they don't need to extend it: they can add a new method as each method is independent and has no chance of breaking other functionalities. So, no need to override it. Also, you are not going to instantiate it, so no need to subclass it. Better to mark it final.
In summary, instantiating a utility class (new MyUtilityClass()) does not make sense. Hence the constructors should be private. And you never want to override or extend it, so mark it final.
It's not necessary, but it is convenient. A utility class is just a namespace holder of related functions and is not meant to be instantiated or subclassed. So preventing instantiation and extension sends a correct message to the user of the class.
There is an important distinction between the Java Language, and the Java Runtime.
When the java class is compiled to bytecode, there is no concept of access restriction, public, package, protected, private are equivalent. It is always possible via reflection or bytecode manipulation to invoke the private constructor, so the jvm cannot rely on that ability.
final on the other hand, is something that persists through to the bytecode, and the guarantees it provides can be used by javac to generate more efficient bytecode, and by the jvm to generate more efficient machine instructions.
Most of the optimisations this enabled are no longer relevant, as the jvm now applies the same optimisations to all classes that are monomorphic at runtime—and these were always the most important.
By default this kind of class normally is used to aggregate functions who do different this, in that case we didn't need to create a new object
In object oriented programming, I have read that you should program to an interface not an implementation but do they mean literal interfaces (no shared code at all)?
Is it okay to program to an abstract base class that would have been an interface except that there were variables in this "interface" that all sub-classes were expected to have? Replicating a variable across sub-classes would have been an inconvenience because if I changed the name of one of the variables in one of the sub-classes I would have to change the name of that variable in all of the sub-classes.
In following the principle of "program to an interface not an implementation", is this okay or would you create another interface on top of the abstract base class and program to that interface?
You want to program to interfaces because it means lower coupling. Note that interfaces in Java are more flexible since they can be implemented by a class anywhere in the class hierarchy unlike abstract classes (as a result of single inheritance). Such flexibility means that your code is reusable to a higher degree.
The important point of "programming to an interface not an implementation" is that of the general principles mentioned above, even if they might cause some minor inconveniences.
Also, even if you program to an interface, you can always implement said interface (or parts of it) by means of abstract classes if you'd like, achieving both low coupling and code reusability at the same time.
It's always okay to program to abstract or even concrete classes, however it's better if you can avoid it.
This discussion might be helpful or this one and of course this one.
Note: C++ doesn't have interfaces. You might argue it doesn't need them.
you should program to an interface not an implementation but do they mean literal interfaces (no shared code at all)?
Possibly. Where it makes sense to do this, it can work very well. Note: in Java interfaces can have code as well.
Is it okay to program to an abstract base class that would have been an interface except that there were variables in this "interface" that all sub-classes were expected to have?
If you need fields in the implementation an abstract class can make sense. You can still use an interface as well.
Replicating a variable across sub-classes would have been an inconvenience because if I changed the name of one of the variables in one of the sub-classes I would have to change the name of that variable in all of the sub-classes.
This is where using an IDE helps. You can change a field, class, method name in all your code with one action.
is this okay or would you create another interface on top of the abstract base class and program to that interface?
You can code your implementation to an abstract class, but the users of that class should be using an interface if possible.
e.g. HashMap extends AbstractMap but implements Map. Most people would use Map not AbstractMap
In java, is there ever a case for allowing a non-abstract class to be extended?
It always seems to indicate bad code when there are class hierarchies. Do you agree, and why/ why not?
There are certainly times when it makes sense to have non-final concrete classes. However, I agree with Kent - I believe that classes should be final (sealed in C#) by default, and that Java methods should be final by default (as they are in C#).
As Kent says, inheritance requires careful design and documentation - it's very easy to think you can just override a single method, but not know the situations in which that method may be called from the base class as part of the rest of the implementation.
See "How do you design a class for inheritance" for more discussion on this.
I agree with Jon and Kent but, like Scott Myers (in Effective C++), I go much further. I believe that every class should be either abstract, or final. That is, only leaf classes in any hierarchy are really apt for direct instantiation. All other classes (i.e. inner nodes in the inheritance) are “unfinished” and should consequently be abstract.
It simply makes no sense for usual classes to be further extended. If an aspect of the class is worth extending and/or modifying, the cleaner way would be to take that one class and separate it into one abstract base class and one concrete interchangeable implementation.
there a good reasons to keep your code non-final. many frameworks such as hibernate, spring, guice depend sometimes on non-final classes that they extends dynamically at runtime.
for example, hibernate uses proxies for lazy association fetching.
especially when it comes to AOP, you will want your classes non-final, so that the interceptors can attach to it.
see also the question at SO
This question is equally applicable to other platforms such as C# .NET. There are those (myself included) that believe types should be final/sealed by default and need to be explicitly unsealed to allow inheritance.
Extension via inheritance is something that needs careful design and is not as simple as just leaving a type unsealed. Therefore, I think it should be an explicit decision to allow inheritance.
Your best reference here is Item 15 of Joshua Bloch's excellent book "Effective Java", called "Design and document for inheritance or else prohibit it". However the key to whether extension of a class should be allowed is not "is it abstract" but "was it designed with inheritance in mind". There is sometimes a correlation between the two, but it's the second that is important. To take a simple example most of the AWT classes are designed to be extended, even those that are not abstract.
The summary of Bloch's chapter is that interaction of inherited classes with their parents can be surprising and unpredicatable if the ancestor wasn't designed to be inherited from. Classes should therefore come in two kinds a) classes designed to be extended, and with enough documentation to describe how it should be done b) classes marked final. Classes in (a) will often be abstract, but not always. For
I disagree. If hierarchies were bad, there'd be no reason for object oriented languages to exist. If you look at UI widget libraries from Microsoft and Sun, you're certain to find inheritance. Is that all "bad code" by definition? No, of course not.
Inheritance can be abused, but so can any language feature. The trick is to learn how to do things appropriately.
In some cases you want to make sure there's no subclassing, in other cases you want to ensure subclassing (abstract). But there's always a large subset of classes where you as the original author don't care and shouldn't care. It's part of being open/closed. Deciding that something should be closed is also to be done for a reason.
I couldn't disagree more. Class hierarchies make sense for concrete classes when the concrete classes know the possible return types of methods that they have not marked final. For instance, a concrete class may have a subclass hook:
protected SomeType doSomething() {
return null;
}
This doSomething is guarenteed to be either null or a SomeType instance. Say that you have the ability to process the SomeType instance but don't have a use case for using the SomeType instance in the current class, but know that this functionality would be really good to have in subclasses and most everything is concrete. It makes no sense to make the current class an abstract class if it can be used directly with the default of doing nothing with its null value. If you made it an abstract class, then you would have its children in this type of hierarchy:
Abstract base class
Default class (the class that could have been non-abstract, only implements the protected method and nothing else)
Other subclasses.
You thus have an abstract base class that can't be used directly, when the default class may be the most common case. In the other hierarchy, there is one less class, so that the functionality can be used without making an essentially useless default class because abstraction just had to be forced onto the class.
Default class
Other subclasses.
Now, sure, hierarchies can be used and abused, and if things are not documented clearly or classes not well designed, subclasses can run into problems. But these same problems exist with abstract classes as well, you don't get rid of the problem just because you add "abstract" to your class. For instance, if the contract of the "doSomething()" method above required SomeType to have populated x, y and z fields when they were accessed via getters and setters, your subclass would blow up regardless if you used the concrete class that returned null as your base class or an abstract class.
The general rule of thumb for designing a class hierarchy is pretty much a simple questionaire:
Do I need the behavior of my proposed superclass in my subclass? (Y/N)
This is the first question you need to ask yourself. If you don't need the behavior, there's no argument for subclassing.
Do I need the state of my proposed superclass in my subclass? (Y/N)
This is the second question. If the state fits the model of what you need, this may be a canidate for subclassing.
If the subclass was created from the proposed superclass, would it truly be an IS-A relation, or is it just a shortcut to inherit behavior and state?
This is the final question. If it is just a shortcut and you cannot qualify your proposed subclass "as-a" superclass, then inheritance should be avoided. The state and logic can be copied and pasted into the new class with a different root, or delegation can be used.
Only if a class needs the behavior, state and can be considered that the subclass IS-A(n) instance of the superclass should it be considered to inherit from a superclass. Otherwise, other options exist that would be better suited to the purpose, although it may require a little more work up front, it is cleaner in the long run.
There are a few cases where we dont want to allow to change the behavior. For instance, String class, Math.
I don't like inheritance because there's always a better way to do the same thing but when you're making maintenance changes in a huge system sometimes the best way to fix the code with minimum changes is to extend a class a little. Yes, it's usually leads to a bad code but to a working one and without months of rewriting first. So giving a maintenance man as much flexibility as he can handle is a good way to go.