Ok I have an abstract class 'Order':
public abstract class Order {
protected String location;
protected double price;
public Order(double price, String location){
this.price = price;
this.location = location;
}
public abstract double calculateBill();
public String getLocation() {
return location;
}
public double getPrice() {
return price;
}
public abstract String printOrder(String format);
}
I also have 3 classes that implement it that are similar except, of course, that they calculateBill differently according to tax, tariff, etc.
now I am trying to create and OrderManager class to manage them. This is what I have so far
public class OrderManager {
private ArrayList<Order> orders;
public OrderManager() {
}
public OrderManager(ArrayList<Order> orders) {
this.orders = orders;
}
public void addOrder(Order o) {
orders.add(o);
}
public ArrayList<Order> getOrdersAbove(double val) {
for (Order o : orders) {
double bill = o.calculateBill();
if (bill > val)
orders.add(o);
}
return orders;
}
I'm having trouble with the getOrdersAbove method which should return and array list of orders whose bill is above val. Being the calculateBill is abstract and implemented in each subclass of order I should just be able to call it correct? Also if that is the case then shouldn't OrderManager extend Order? Or just being in the same package would allow me to call it's methods? Or am I going about it all wrong?
Thanks for any and all help!
Being the calculateBill is abstract and implemented in each subclass
of order I should just be able to call it correct?
The method is declared as public, you will be able to call it on Order instances.
Also if that is the case then shouldn't OrderManager extend Order?
Ask yourself: is an OrderManager an Order? No? So don't make it extend Order.
Or just being in the same package would allow me to call it's methods?
Again, the method is public, so you can call it from anywhere as long as you have an instance to call it on.
So in your for loop
public ArrayList<Order> getOrdersAbove(double val) {
for (Order o : orders) {
double bill = o.calculateBill();
// do logic
}
}
When calling calculateBill(), Java will use late-binding (polymorphism) to resolve the actual implementation of the method to use.
Your OrderManager doesn't need to know anything about the calculateBill method of subclasses of Order.
As long as the method is overriden you can be sure that you will be allowed to invoke it if it's public (or they're in same package) since you can't reduce the visibility of an inherited method.
Even if Order is abstract and calculateBill is abstract in that class that doesn't forbid you from calling the method. The only restriction which is applied to abstract classes is that you can't instantiate them, once you have an instance (even if its runtime type is narrower) then you shouldn't worry about anything.
Being the calculateBill is abstract and implemented in each subclass of order I should just be able to call it correct?
Java Runtime doesn't really care that there's no implementation of the calculateBill() method in Order, just that Order "knows about" (or maybe better yet, "has declared") a method called calculateBill() which accepts no arguments and returns a double -- which it does because of your line:
public abstract double calculateBill();
Ensuring that concrete subclasses actually implement the abstract method is a check done at compile time. As long as you've overridden the calculateBill() methods in the subclasses (which you would need to do for the code to compile), you'll be able to call it (from anywhere, since you declared it as public). The specific implementation calculateBill() -- that is whether it's class Foo's implementation or class Bar's -- will be selected for you at runtime, based on the specific subclass instance you're calling it on.
Also if that is the case then shouldn't OrderManager extend Order?
No. I don't see why it should. It doesn't seem to make a ton of sense. If you did, you'd have to have a concrete implementation of calculateBill() inside OrderManager which similarly doesn't seem to make a ton of sense.
Or just being in the same package would allow me to call it's methods?
Public (nonstatic) methods (which calculateBill() is) are callable by anyone who has an instance of the class, whether the calling class is within the same package or not.
Or am I going about it all wrong?
You seem to be on the right track with abstract methods and implementations in the subclasses, as well as providing default implementations of various methods in the abstract class (e.g. getPrice(), getLocation())
getOrdersAbove should create a new ArrayList to hold the orders above val.
You are adding the selected orders back to the list you are iterating over which will cause the iterator to fail.
Related
I have an abstract class that performs basic operations, now I want to force every derived class to have a method "check", but the point is I know nothing about this method. For example, the abstract class:
public abstract class Service<T extends Transport> {
public T getTransport(int id) {
[...]
}
public abstract boolean checkTransport(T transport, ...);
}
and two implementing classes:
public ServiceAAA extends Service<ClassA> {
public boolean checkTransport(ClassA t) {
[...]
}
}
public ServiceBBB extends Service<ClassB> {
public boolean checkTransport(ClassB t, Integer value, Integer otherValue) {
[...]
}
}
The ServiceBBB needs two parameter to check the object t of class ClassB.
Of course it's not working, is there a way to force the subclass to implement the checkTransport method without using the "Object ... " notation?
No, there isn't.
Let's pretend there were a way. How would you invoke this method, either from the abstract Service class, or from any call site that had a reference to this object typed as Service<...>? There'd be no way of knowing what the specific subclass's method expects, and thus no way of invoking the method.
One way around this is to pass the checker in as a class to Service; that is, to use composition instead of inheritance. If you do that, you can have the checker's interface take no extra arguments at all (a Predicate might work, for instance), and the specific subclasses that implement that checker could have the arguments passed at construction time.
"Return an immutable interface to the original data. You can then change fields in the object, but the caller cannot unless he cheats by casting. You expose only the methods you want the user to have. Doing the same with classes is trickier since a subclass must expose everything its superclass does"
What does he mean you can cheat, and why is it tricky with subclasses ?
source: http://mindprod.com/jgloss/immutable.html
You provide an interface that has no mutation methods. Then, you provide mutable implementations that are only known to the creator.
public interface Person
{
String getName();
}
public class MutablePerson implements Person
{
private String name;
public MutablePerson(String name)
{
this.name = name;
}
#Override
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
}
At this point, if you return Person objects everywhere, the only way for someone to modify the returned object is to cheat and cast it back to a MutablePerson. In effect, the mutable objects become immutable unless the code is a complete hack.
Person person = new MutablePerson("picky");
// someone is cheating:
MutablePerson mutableAgain = (MutablePerson)person;
mutableAgain.setName("Phoenix");
// person.getName().equals("Phoenix") == true
When not dealing with a bunch of younger programmers that will notice the true implementation is mutable, and thus they can cast it to change it, then you provide the safety of immutability with the benefit of being able to put it together without an endless constructor, or using a Builder (in effect, the mutable version is the Builder). A good way to avoid developers abusing the mutable version is to leave the mutable version as package private so that only the package knows about it. The negative of that idea is that this only works if it will be instantiated in the same package, which may be the case, but it obviously may not be the case in situations such as where DAO's are used with multiple package-defined implementations (e.g., MySQL, Oracle, Hibernate, Cassandra, etc., all returning the same stuff, and hopefully separated from each other to avoid cluttering their packages).
The real key here is that people should never build up from the Mutable objects except to implement further-down interfaces. If you're extending, and then returning an immutable subclass, then it's not immutable if it exposes a mutable object, by definition. For example:
public interface MyType<T>
{
T getSomething();
}
public class MyTypeImpl<T> implements MyType<T>
{
private T something;
public MyTypeImpl(T something)
{
this.something = something;
}
#Override
public T getSomething()
{
return something;
}
public void setSomething(T something)
{
this.something = something;
}
}
public interface MyExtendedType<T> extends MyType<T>
{
T getMore();
}
public class MyExtendedTypeImpl<T>
extends MyTypeImpl<T>
implements MyExtendedType<T>
{
private T more;
public MyExtendedTypeImpl(T something, T more)
{
super(something);
this.more = more;
}
#Override
public T getMore()
{
return more;
}
public void setMore(T more)
{
this.more = more;
}
}
This is honestly the way that Collections in Java should have been implemented. A readonly interface could have taken the place of the Collections.unmodifiable implementations, thus not having people unexpectedly using immutable versions of mutable objects. In other words, you should never hide immutability, but you can hide mutability.
Then, they could sprinkle immutable instances that truly can't be modified, and that would keep developers honest. Similarly, I would likely expect to see an immutable version of the above interface somewhere (with better names):
public class MyTypeImmutable<T> implements MyType<T>
{
private final T something;
public MyTypeImmutable(T something)
{
this.something = something;
}
#Override
public T getSomething()
{
return something;
}
}
I think that statement is not well worded, and he's touching on more than just immutability (and in fact, what that statement is not even really immutability).
The idea is that if you return an interface to the data, and not the specific class, the caller should only perform the actions on the interface. So if your interface only has getter methods, then there should be no way to manipulate the data (without downcasting).
Consider this hierarchy
interface AnInterface {
void aGetter();
}
class MyMutableClass {
void aGetter();
void aSetter(...);
}
Even though MyMutableClass is mutable, by returning AnInterface, the user doesn't know it's actually a mutable object. So the object isn't actually mutable, but you would have to downcast (or use reflection to access the mutator methods) to know that.
Now let's say you had
class MyImmutableSubclass extends MyMutableClass {
void anotherGetter();
}
Even though the subclass is "immutable" (which it's not really since its parent class is not immutable), if you return MyImmutableSubclass from the method, the caller can still call aSetter since MyMutableClass exposes it.
In general, using immutable objects is recommended to avoid "leaking" state. Anything that is truly immutable is safe from any manipulation and unintended changes.
You can cheat because you can change the type of the returned fields if you typecast to "something" mutable. If you "hide" your class behind a public interface and return that immutable interface, the user can cheat by typecasting your interface to your class.
With subclasses is trickier because any private members of a class are not inherited by the subclass but protected and public are. That means anything that you can access in your parent class from the outside can be accessed in the children from the outside too, so you can't really obfuscate the user as easily as you would with an interface. This is actually possible, i think, since you can override the parent methods, although I don't see much point in it.
I know abstract fields do not exist in java. I also read this question but the solutions proposed won't solve my problem. Maybe there is no solution, but it's worth asking :)
Problem
I have an abstract class that does an operation in the constructor depending on the value of one of its fields.
The problem is that the value of this field will change depending on the subclass.
How can I do so that the operation is done on the value of the field redefined by the subclass ?
If I just "override" the field in the subclass the operation is done on the value of the field in the abstract class.
I'm open to any solution that would ensure that the operation will be done during the instantiation of the subclass (ie putting the operation in a method called by each subclass in the constructor is not a valid solution, because someone might extend the abstract class and forget to call the method).
Also, I don't want to give the value of the field as an argument of the constructor.
Is there any solution to do that, or should I just change my design ?
Edit:
My subclasses are actually some tools used by my main program, so the constructor has to be public and take exactly the arguments with which they will be called:
tools[0]=new Hand(this);
tools[1]=new Pencil(this);
tools[2]=new AddObject(this);
(the subclasses are Hand, Pencil and AddObject that all extend the abstract class Tool)
That's why I don't want to change the constructor.
The solution I'm about to use is to slightly change the above code to:
tools[0]=new Hand(this);
tools[0].init();
tools[1]=new Pencil(this);
tools[1].init();
tools[2]=new AddObject(this);
tools[2].init();
and use an abstract getter to acces the field.
How about abstract getter/setter for field?
abstract class AbstractSuper {
public AbstractSuper() {
if (getFldName().equals("abc")) {
//....
}
}
abstract public void setFldName();
abstract public String getFldName();
}
class Sub extends AbstractSuper {
#Override
public void setFldName() {
///....
}
#Override
public String getFldName() {
return "def";
}
}
Also, I don't want to give the value
of the field as an argument of the
constructor.
Why not? It's the perfect solution. Make the constructor protected and offer no default constructor, and subclass implementers are forced to supply a value in their constructors - which can be public and pass a constant value to the superclass, making the parameter invisible to users of the subclasses.
public abstract class Tool{
protected int id;
protected Main main;
protected Tool(int id, Main main)
{
this.id = id;
this.main = main;
}
}
public class Pencil{
public static final int PENCIL_ID = 2;
public Pencil(Main main)
{
super(PENCIL_ID, main);
}
}
How about using the Template pattern?
public abstract class Template {
private String field;
public void Template() {
field = init();
}
abstract String init();
}
In this way, you force all subclasses to implement the init() method, which, since it being called by the constructor, will assign the field for you.
You can't do this in the constructor since the super class is going to be initialized before anything in the subclass. So accessing values that are specific to your subclass will fail in your super constructor.
Consider using a factory method to create your object. For instance:
private MyClass() { super() }
private void init() {
// do something with the field
}
public static MyClass create() {
MyClass result = new MyClass();
result.init();
return result;
}
You have an issue in this particular sample where MyClass can't be subclassed, but you could make the constructor protected. Make sure your base class has a public / protected constructor also for this code. It's just meant to illustrate you probably need two step initialization for what you want to do.
Another potential solution you could use is using a Factory class that creates all variants of this abstract class and you could pass the field into the constructor. Your Factory would be the only one that knows about the field and users of the Factory could be oblivious to it.
EDIT: Even without the factory, you could make your abstract base class require the field in the the constructor so all subclasses have to pass in a value to it when instantiated.
Also, I don't want to give the value of the field as an argument of the constructor.
Is there any solution to do that, or should I just change my design ?
Yes, I think you should change your design so that the subclass passes the value to the constructor. Since the subclass portion of your object isn't initialized until after the superclass constructor has returned, there's really no other clean way of doing it. Sure, this'd work:
class Super {
protected abstract int abstractField();
protected Super() { System.out.println("Abstract field: " + abstractField); }
}
class Sub {
protected int abstractField(){ return 1337; }
}
... since the implementation of abstractField() doesn't operate on object state. However, you can't guarantee that subclasses won't think it's a great idea to be a little more dynamic, and let abstractField() returns a non-constant value:
class Sub2 {
private int value = 5;
protected int abstractField(){ return value; }
public void setValue(int v){ value = v; }
}
class Sub3 {
private final int value;
public Sub3(int v){ value = v; }
protected int abstractField(){ return value; }
}
This does not do what you'd expect it to, since the initializers and constructors of subclasses run after those of the superclass. Both new Sub2() and new Sub3(42) would print Abstract field: 0 since the value fields haven't been initialized when abstractField() is called.
Passing the value to the constructor also has the added benefit that the field you store the value in can be final.
If the value is determined by the type of subclass, why do you need a field at all? You can have a simple abstract method which is implemented to return a different value for each subclass.
I think you need a factory (aka "virtual constructor") that can act on that parameter.
If it's hard to do in a given language, you're probably thinking about it incorrectly.
If I understand you correctly: You want the abstract class's constructor to do something depending on a field in the abstract class but which is set (hopefully) by the subclass?
If I got this wrong you can stop reading ...
But if I got it right then you are trying to do something that is impossible. The fields of a class are instantiated in lexical order (and so if you declare fields "below", or "after", the constructor then those will not be instantiated before the constructor is called). Additionally, the JVM runs through the entire superclass before doing anything with the subclass (which is why the "super()" call in a subclass's constructor needs to be the first instruction in the constructor ... because this is merely "advice" to the JVM on how to run the superclass's constructor).
So a subclass starts to instantiate only after the superclass has been fully instantiated (and the superclass's is constructor has returned).
And this is why you can't have abstract fields: An abstract field would not exist in the abstract class (but only in the subclass) and so is seriously(!) "off limits" to the super (abstract) class ... because the JVM can't bind anything references to the field (cause it doesn't exist).
Hope this helps.
I know it's not possible to define a constructor in an interface. But I'm wondering why, because I think it could be very useful.
So you could be sure that some fields in a class are defined for every implementation of this interface.
For example consider the following message class:
public class MyMessage {
public MyMessage(String receiver) {
this.receiver = receiver;
}
private String receiver;
public void send() {
//some implementation for sending the mssage to the receiver
}
}
If a define an interface for this class so that I can have more classes which implement the message interface, I can only define the send method and not the constructor. So how can I ensure that every implementation of this class really has an receiver set? If I use a method like setReceiver(String receiver) I can't be sure that this method is really called. In the constructor I could ensure it.
Taking some of the things you have described:
"So you could be sure that some fields in a class are defined for
every implementation of this interface."
"If a define a Interface for this class so that I can have more
classes which implement the message interface, I can only define the
send method and not the constructor"
...these requirements are exactly what abstract classes are for.
A problem that you get when you allow constructors in interfaces comes from the possibility to implement several interfaces at the same time. When a class implements several interfaces that define different constructors, the class would have to implement several constructors, each one satisfying only one interface, but not the others. It will be impossible to construct an object that calls each of these constructors.
Or in code:
interface Named { Named(String name); }
interface HasList { HasList(List list); }
class A implements Named, HasList {
/** implements Named constructor.
* This constructor should not be used from outside,
* because List parameter is missing
*/
public A(String name) {
...
}
/** implements HasList constructor.
* This constructor should not be used from outside,
* because String parameter is missing
*/
public A(List list) {
...
}
/** This is the constructor that we would actually
* need to satisfy both interfaces at the same time
*/
public A(String name, List list) {
this(name);
// the next line is illegal; you can only call one other super constructor
this(list);
}
}
An interface defines a contract for an API, that is a set of methods that both implementer and user of the API agree upon. An interface does not have an instanced implementation, hence no constructor.
The use case you describe is akin to an abstract class in which the constructor calls a method of an abstract method which is implemented in an child class.
The inherent problem here is that while the base constructor is being executed, the child object is not constructed yet, and therfore in an unpredictable state.
To summarize: is it asking for trouble when you call overloaded methods from parent constructors, to quote mindprod:
In general you must avoid calling any
non-final methods in a constructor.
The problem is that instance
initialisers / variable initialisation
in the derived class is performed
after the constructor of the base
class.
A work around you can try is defining a getInstance() method in your interface so the implementer is aware of what parameters need to be handled. It isn't as solid as an abstract class, but it allows more flexibility as being an interface.
However this workaround does require you to use the getInstance() to instantiate all objects of this interface.
E.g.
public interface Module {
Module getInstance(Receiver receiver);
}
There is only static fields in interface that dosen't need to initialized during object creation in subclass and the method of interface has to provide actual implementation in subclass .So there is no need of constructor in interface.
Second reason-during the object creation of subclass, the parent constructor is called .But if there will be more than one interface implemented then a conflict will occur during call of interface constructor as to which interface's constructor will call first
If you want to make sure that every implementation of the interface contains specific field, you simply need to add to your interface the getter for that field:
interface IMyMessage(){
#NonNull String getReceiver();
}
it won't break encapsulation
it will let know to everyone who use your interface that the Receiver object has to be passed to the class in some way (either by constructor or by setter)
Dependencies that are not referenced in an interfaces methods should be regarded as implementation details, not something that the interface enforces. Of course there can be exceptions, but as a rule, you should define your interface as what the behavior is expected to be. Internal state of a given implementation shouldn't be a design concern of the interface.
This is because interfaces do not allow to define the method body in it.but we should have to define the constructor in the same class as interfaces have by default abstract modifier for all the methods to define. That's why we can not define constructor in the interfaces.
See this question for the why (taken from the comments).
If you really need to do something like this, you may want an abstract base class rather than an interface.
Here´s an example using this Technic. In this specifik example the code is making a call to Firebase using a mock MyCompletionListener that is an interface masked as an abstract class, an interface with a constructor
private interface Listener {
void onComplete(databaseError, databaseReference);
}
public abstract class MyCompletionListener implements Listener{
String id;
String name;
public MyCompletionListener(String id, String name) {
this.id = id;
this.name = name;
}
}
private void removeUserPresenceOnCurrentItem() {
mFirebase.removeValue(child("some_key"), new MyCompletionListener(UUID.randomUUID().toString(), "removeUserPresenceOnCurrentItem") {
#Override
public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) {
}
});
}
}
#Override
public void removeValue(DatabaseReference ref, final MyCompletionListener var1) {
CompletionListener cListener = new CompletionListener() {
#Override
public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) {
if (var1 != null){
System.out.println("Im back and my id is: " var1.is + " and my name is: " var1.name);
var1.onComplete(databaseError, databaseReference);
}
}
};
ref.removeValue(cListener);
}
Generally constructors are for initializing non-static members of particular class with respect to object.
There is no object creation for interface as there is only declared methods but not defined methods. Why we can’t create object to declared methods is-object creation is nothing but allocating some memory (in heap memory) for non-static members.
JVM will create memory for members which are fully developed and ready to use.Based on those members , JVM calculates how much of memory required for them and creates memory.
Incase of declared methods, JVM is unable to calculate the how much memory will required to these declared methods as the implementation will be in future which is not done by this time. so object creation is not possible for interface.
conclusion:
without object creation, there is no chance to initialize non-static members through a constructor.That is why constructor is not allowed inside a interface.(as there is no use of constructor inside a interface)
Why do we need constructors and private members in the abstract class? It is not like we are ever going to create an instance of that class.
You will create instances, just instances of a derived class. Those derived classes will still need to call constructors, and can still call members of the abstract class - which may in turn use private members.
Here's an example (not a terribly useful one, but just to show the basic idea...)
public abstract class NamedObject
{
private final String name = name;
protected NamedObject(String name)
{
this.name = name;
}
public String getName()
{
return name;
}
}
public class Computer extends NamedObject
{
private final int processorSpeed;
public Computer(String name, int processorSpeed)
{
super(name); // See, the constructor is useful
this.processorSpeed = processorSpeed;
}
public String toString()
{
return getName() + " (" + processorSpeed + ")";
}
}
I can't say I write abstract classes that often, generally preferring composition to inheritance, but when I do create them I certainly use constructors and private members.
Abstract classes provide a partial implementation of some interface. It's perfectly reasonable to consider that you might want to provide part of that implementation and disallow client code (concrete subclasses) from accessing the specifics - i.e. an extension of the principle of encapsulation.
Marking some members as private forces the inheriting class to call protected methods to access that partial implementation; providing a constructor allows for subclasses to initialise the parent's encapsulated state during their own construction.
Unlike an interface, an abstract class that defines data fields is in fact instantiated in the sense that these data fields are allocated. It is just that they are never instantiated on their own, they are instantiated as part of something bigger - the subclass. So when the subclass is built, the supertype is built as well, which is why you would need a constructor.
Depending on your hierarchy, your abstract class may have a meaning and state. For example, if your application is a school you may have the notion of a person (that has a name and an SSN), but you would have different subtypes for students and for faculty. Because both types of people share certain state structure (name and SSN) you would have both classes extend the Person class. But you would never simply instantiate a person directly.
In addition to Jon's answer, I'd like to mention that abstract classes still go well with composition, if you keep the subclass tree shallow. I.e. it is great for providing a common base class for a few closely related objects, but not for creating a gigantic tree of subclasses.
Why do you need private class? I think that you are confusing abstract classes with interfaces. Unlike interfaces, abstract classes can hold functionality. For example:
public class AbstractBase{
private int num;
public AbstractBase(int number){
this->num = number;
}
public int method(){
return ( this->num * this->templateMethod());
}
public abstract int templateMethod();
}
public class ConcreteDerived extends AbstractBase{
public ConcreteDerived(){
super(4);
}
public int templateMethod(){
return number; //number is the result of some calculation
}
}
In this example, you´ll never explicitly instantiate AbstractBase, but by declaring members and constructors, you can customize the functionality of your classes (this is called template method).
Assuming you're doing ad hoc code or prototyping, you do instantiate abstract classes (or maybe even interfaces) from time to time. They're called anonymous inner classes (one, two) and look like this:
// you have this...
public abstract class SomeClass {
public abstract String returnAString();
}
// ...and this...
public class OtherClass {
public void operate(SomeClass c) {
System.out.println(c.returnAString());
}
}
// ...so you do this:
OtherClass oc = new OtherClass();
// this is one of the reasons why you need to specify a constructor
oc.operate(new SomeClass() {
#Override
public String returnAString() {
return "I'm an anonymous inner class!";
}
});
This example is of course quite redundant but should expose the point. Some existing frameworks even rely on the heavy usage of this behaviour, namely Apache Wicket at least.