I have an abstract super class and several subclasses that inherit fields defined in the super class, but each subclass has different values for those fields. When the subclass is called, I use the constructor to set the fields appropriately.
Should I use direct references to do this field = value, or should I use the super class set methods setField(value);?
I'd rather keep the fields private, so I want to avoid direct references.
The other alternative is to call the super constructor, which would allow me to use direct references in the super class constructor super (T value) and in the super class SuperClass(T value){ field = value}. Would this be the best way? I could even use set methods inside the super constructor, but this seems like it would be redundant.
One great advantage and one great reason why abstract superclasses are used is to save coding time and make your class architecture that much easier.
Therefore, if you have a superclass that has common fields with subclasses, then you should take a second look at your architecture.
To solve your problem, remove any redundant fields that are in the subclasses but already exist in the superclass. Whenever you want to utilize the fiels, simply use the superclasses reference. Call for instance the superclasses constructor to set the values for the fields etc.
Whenever you want to retrieve the fields, call "super.getValue(...)" etc
In general, you should make them private and access them using getters and setters. If subclasses are allowed to set them directly, they could violate the contracts of the superclass by setting invalid values.
And if the subclasses differ only in the values of those superclass fields, then you shouldn't use subclasses at all; just create instances of the superclass with different values.
Related
I've created an abstract class contains a method with an implementation. This method is called by subclasses to populate a list, which should be shared amongst all instances of each individual subclass (like an abstract static field which is different and static to each subclass). The issue is: abstract static fields do not exist, so how else might I be able to achieve this behaviour?
For context, the implemented method on the abstract class is for resolving classes from an unqualified name via the reflections8 package. This method calls an abstract method to get the packages to reflect, which just returns a String[] (as subclasses will want to search in different packages). This method then generates a Map<String, Class<?>> containing a mapping of the name of each reflected class to the Class, which is what I would like to share between instances of each specific subclass type (so that it doesn't have to reflect for the same subclass more than once). Ultimately, this method is called by the subclass in order to instantiate a class from its unqualified name.
Please forgive me if this is a rather strange way of doing things; I come from the land of iOS where we don't have package names attached to class names (so I can just call NSClassFromString("ClassName") and that's it).
EDIT: Check out this gist for the current implementation (and check out the comment for a usage example).
My thoughts: if you're wanting your subclasses to have their own respective static fields, it's best to just have those static fields declared in them rather than this abstract class.
From what I understand, your abstract class is really just a placeholder for this one implemented method. Do any of your subclasses override anything from the parent? If not, maybe it doesn't need to be an abstract class.
Plus, does your abstract class need any state? Because if not, you might be better off with this: change your abstract class to be a static class, and your implemented method be a static method, which accepts an "ClassName" argument. Then in your subclasses you can just directly call the method with your subclass' static fields using something akin to MyStaticClass. NSClassFromString(subclassStaticField);
There is no equivalent for abstract static for fields:
An instance field cannot be abstract. It really makes no sense. abstract means we are deferring some of the details to a subclass. But for an instance field there is nothing that it makes sense to defer.
A static field is not inherited anyway, so there is no way one could be used polymorphically. static fields with the same name in different classes are distinct variables.
You can (of course) use reflection to test if a field (static or instance) has been declared ... but that's not what abstract means in Java.
Solution:
If you want an instance field to exist in all of the subclasses of an abstract class, declare it as a regular field in the abstract class.
If you want a static field to exist in all subclasses, you have no choice but to explicitly declare it in each subclass. You won't be able to use it / them polymorphically.
This question is mainly in reference to Luiggi's answer to this SO question:
Why can you not inherit from a class whose constructor is private?
I understand that Java enforces that every subclass constructor must call one of its superclass's constructors. If all the superclass's constructors are private, this is obviously not possible. So, if a subclass theoretically could inherit from a superclass with private constructors, the result would be that you couldn't call a constructor on the subclass.
But what if I never intend to create an instance of the subclass anyway? For example, what if my subclass only adds static fields and methods, and I'm only interested in using the static fields and methods of the superclass? Then I don't need a constructor for the subclass.
what if my subclass only adds static fields and methods, and I'm only
interested in using the static fields and methods of the superclass
In that case you don't need inheritance - use composition!
You should seal your class by declaring it as final. Then it is guaranteed that no sub-classes can be made
If only adding subclasses and can only create the parent class, the child "class" is really just a helper class without adding any functionality/responsibilites/etc. to the parent. In many respects, it's meaningless.
A subclass of this sort would not be a legitimate subclass. Even if all of its fields and methods were declared static, it would inherit all of the fields and methods of all of its superclasses, all the way back up to Object. And there are non-static methods in Object. So this subclass would have some set of non-static methods (and possibly fields) in its declaration.
This subclass could then be used as a type of a field, variable, type parameter or method argument (i.e. anywhere a type can be used). The compiler would have to keep track of the fact that this particular type could only be used in some restricted sense. (Imagine a method that returned a value of this subclass for example).
There are, I'm sure, many more gotcha's for this sort of thing.
So, bottom line, it would make writing a compiler really hard.
I need to make my inherited instance variables private; is this possible?
IE, Superclass "Entity" has an int instance variable "health".
How can subclass "Zombie" (Extends "Entity") inherit the health variable from Entity, and have it private? I don't want other classes to be able to directly access the health variable, I want set and get methods for it.
Tell me if I wasn't specific enough; any help appreciated.
Simply : you can't.
This would break the contract of the superclass. Your class, being an Entity, exposes, like its superclass, a field named health. If you had the ability to make it private, all code using this field in instances of Entity (including instances of subclasses of Entity) would break with your class...
If you can, change the superclass (ie Entity) to make the field private. That's the common practice.
Make the variable private in the superclass and let all subclasses use accessor methods.
A second choice would be to make it package-private and arrange for those classes to which you want to deny access to be in another package. This would make sense if your Zombie is especially close to Entity (shares many internals) whereas other classes are more loosely coupled to their superclass.
You cannot decrease the visibility of any instance variable or method of the super class in your subclass..
Suppost you have super class with a public method.. And, suppose you were allowed to decrease the visibility to private in sub class..
Then see what's happens when you create object like this, and access that method of super class: -
SuperClass obj = new SubClass();
obj.pubMethod();
Now, at compile time, compiler sees that method pubMethod() is public in SuperClass, it will allow the access.. Note it does not check for the instance type on the RHS..
Now, at runtime, when JVM checks that the instance is of SubClass, then the actual method it would try to invoke will be searched in the SubClass..
But wait.. Did you see what happened when JVM went to search for pubMethod in SubClass that you made private.. BOoooooMMM -- A Crash..
That's why it is not allowed..
So, you cannot make it private..
From JLS Section - 8.4.8.3: -
The access modifier (ยง6.6) of an overriding or hiding method must
provide at least as much access as the overridden or hidden method, or
a compile-time error occurs. In more detail:
If the overridden or hidden method is public, then the overriding or hiding method must be public; otherwise, a compile-time error
occurs.
If the overridden or hidden method is protected, then the overriding or hiding method must be protected or public; otherwise,
a compile-time error occurs.
If the overridden or hidden method has default (package) access, then the overriding or hiding method must not be private;
otherwise, a compile-time error occurs.
You cannot add restrictions to an instance variable in a subclass, i.e. of health is protected in Enitity it cannot be private in Zombie (you can make it public).
However, you can make health private in Entity and define a protected getter and setter there. Subclasses can use these methods.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Java Constructor Inheritance
When creating subclasses,
Why do I have to create a constructor and write super in every ctor?
If my behavior is similiar to the superclass shouldnt I expect to inherit them as well?
Constructors aren't inherited because you're not creating an instance of the superclass, you're creating an instance of a new class. There's no way to know which superclass constructor you want to call.
To be fair, the default (no arg constructor) always exists. It's the specific arg ctors that you're referring to, I'm assuming.
In reality, java always creates new constructors for your subclasses, but only for the default, no parameters constructor. If your class has constructors other than the default (no parameters) constructor, you have to define them again... Constructors are not meant to be behaviour methods but rather object initialization (which may change for subclasses with new attributes)
Default no argument Constructor is inherited and called by default. In case you like to call another one, you can use super() . In case default constructor can not be used, you have to use one4 of accessible super constructors
Constructors have the same name as the class name and if you're able to inherit them into the subclasses, they can no longer be constructors of subclasses. The default parameterless constructor is always inherited though.
Constructors are invoked to create objects from the class blueprint, ie, to initialise the data members of a class. If a subclass were to inherit a constructor,then while calling a subclass you need to have the knowledge about the parent class' data members too. That is not what one would see in real life scenario. For example, if you create an object of type Ferrari, you would definitely be interested about initialising parameters like speed,acceleration and you would not bother about initialising the parameters of a Car object, even though Ferrari inherits from Car. Therefore, while calling the constructor of a Ferrari, you would only and only be bothered about the members of Ferrari and not the members of its parent class. I hope to have made my point clear.
I have an abstract java class that implements a couple of its methods, but not others. In the methods it implements it uses a private attribute variable. The variable used also needs to be used in a subclass.
As I see it my options are:
Declare the private variable in both the subclass and the super class
defer the implementation of the methods currently implemented in the abstract class to the subclasses
Are there other options? Which of these makes more sense and why?
The question is how you want to maintain your state: If it is of no concern, where the value is stored, you can just add a private member "on top" of the other and use that instead of the one in the superclass. If you want to have some methods from your superclass and some methods from your subclass to access the same state, you need to change visibility:
You could declare the variable as protected, making it accessible in the subclass, or implement accessor methods, or even make it public.
Hopefully the abstract class has been designed such that you shouldn't need access to the private fields. As to which of your two methods to use, that depends entirely on what the abstract class and your subclass are and what they're supposed to be doing.
If you only need read access to this variable and the superclass methods don't modify it, you can just add another (completely separate) private field of the same name/type to your subclass. If you're attempting to modify the behaviour of the superclass methods by changing the field, you're going to have to override the methods instead.