Whenever I create an instance of superclass, I want it to automatically create one instance of the subclass. Then I can access the subclass from an instance of the superclass.
Here I have a superclass name "SortArticles":
public class SortArticles {
private String title;
private String linkToFullArticles;
private FullArticle fullArticleObject;
public String getTitle() {
return this.title;
}
public FullArticle getFullArticleObject() {
return this.fullArticleObject;
}
}
Here I have a subclass name "FullArticle":
public class FullArticle extends SortArticles {
private List<Label> labelList;
}
I want to call like this:
ArrayList<SortArticles> sortList = new ArrayList<>();
sortList.add(new SortArticles());
sortList.get(0).getFullArticleObject().getTitle;
Is it possible to do that? I think of using HashMap to link sort and full, but I need create 2 arraylist, and link it manually.
You are misunderstanding the concept of inheritance.
You can say, that dog is an animal, but you can't know, that the animal, generally, barks, for sure.
It's children, who get properties of parents, not vice versa. When you instantiate some SuperClass, it's not instantiated along with its subclass(es) members, and it should never be.
For example, if you instantiate java.lang.Object, it should never (and it will never) have any members of your (let's say) Employee class; however, your Employee will always inherit all the non-private members of all its parents.
Besides, imagine you have hundred classes extending one SuperClass. Would you expect (or would you want, after all) the instance of your SuperClass, to contain all the non-private members of all hundred classes deriving from it? shall instance of java.lang.Object contain all the non-private infrastructure available on the class-path?
No, that's bad, that's wrong, that's not logical.
Related
Suppose I have these classes:
public class ChildClass extends ParentClass
{
// some class definition here
}
public abstract class ParentClass
{
public static void printClass()
{
// get the class that extends this one (and for example, print it)
}
// some class definition here
}
Lets say when calling ParentClass.printClass() I want to print the name of the class (like doing System.out.println(ParentClass.class)). When then extending ParentClass (for example like in ChildClass) and calling ChildClass.printClass(), I want it to print the name of the extending class (like doing System.out.println(ChildClass.class)). Is this somehow possible?
I've found a way to get the class from inside a static method by using MethodHandles.lookup().lookupClass(), but when using it inside of ParentClass.printClass and extending ParentClass, then calling printClass on the extending Class, I always get the class of ParentClass.
static methods are best thought of as living entirely outside of the class itself. The reason they do show up in classes is because of the design of java (the language) itself: Types aren't just types with a hierarchy, they also serve as the primary vehicle for java's namespacing system.
Types live in packages, packages are the top level namespace concept for types. So how do you refer to a method? There's only one way: Via the type system. Hence, static methods do have to be placed inside a type. But that's about where it ends.
They do not inherit, at all. When you write:
ChildClass.lookupClass()
The compiler just figures out: Right, well, you are clearly referring to the lookupClass() method in ParentClass so that is what I will compile. You can see this in action yourself by running javap -c -p MyExample. The same principle applies to non-static methods, even.
For instance methods, the runtime undoes this maneuvre: Whenever you invoke a method on any object, the runtime system will always perform dynamic dispatch; you can't opt out of this. You may write:
AbstractList<String> list = new ArrayList<String>();
list.sort(someComparator);
and you can use javap to verify that this will end up writing into the class file that the method AbstractList::sort is invoked. But, at runtime the JVM will always check what list is actually pointing at - it's an instance of ArrayList, not AbstractList (that's obvious: AbstractList is abstract; no object can ever be directly instantiated as `new AbstractList). If ArrayList has its own take on the sort method, then that will be called.
The key takeaway of all that is: Static methods do not inherit, therefore, this dynamic dispatch system is not available to them, therefore, what you want cannot be done in that fashion.
So what to do?
It feels like what you're doing is attempting to associate a hierarchy to properties that apply to the class itself. In other words, that you want there to be a hierarchical relationship between the notion of 'ParentClass's lookupClass method and ChildClass's lookupClass method - lookupClass is not a thing you ask an instance of ChildClass or ParentClass - you ask it at the notion of the these types themselves.
If you think about it for a moment, constructors are the same way. You don't 'ask' an instance of ArrayList for a new arraylist. You ask ArrayList, the concept. Both 'do not really do' inheritance and cannot be abstracted into a type hierarchy.
This is where factory classes come in.
Factory classes as a concept are just 'hierarchicalizing' staticness, by removing static from it: Create a sibling type to your class hierarchy (ParentClassFactory for example):
abstract class ParentClassFactory {
abstract ParentClass create();
abstract void printClass();
}
and then, in tandem with writing ChildClass, you also write ChildClassFactory. Generally factories have just one instance - you may want to employ the singleton pattern for this. Now you can do it just fine:
class ChildClassFactory extends ParentClassFactory {
private static final ChildClassFactory INSTANCE = new ChildClassFactory();
public static ChildClassFactory instance() { return INSTANCE; }
public ParentClass create() { return new ChildClass(); }
public void printClass() { System.out.println(ChildClass.class); }
}
// elsewhere:
// actually gets the ChildClassFactory singleton:
ParentClassFactory factory = ....;
factory.printClass(); // will print ChildClass!
Quoting #RealSkeptic:
Static methods are not inherited. The fact that you can call ChildClass.printClass() is just syntactic sugar. It actually always calls ParentClass.printClass(). So you can't do something like that with a static method, only an inheritable non-static one.
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 have a superclass like this which I expect alot of classes to inherit:
public abstract class Super {
protected Object myField; //Not used anywhere in this class
//a load more code here which does useful stuff
}
All these classes will need to use an instance of myField. However the superclass does not. Have I made a bad design decision somewhere?
Not necessarily. If all the subclasses need the same field for the same reason, then that's no different than providing any other common functionality in a base class. as your classes grow you may find that you add common functionality which uses this field (e.g. referencing it in an equals/hashCode method).
Now, if the field is of type Object and each sub-class shoves something completely different into it, i would consider that a code smell.
Well IMHO, a field should not be present in a class if it's not really used by that class. What it seems to me that you really want here is to have a base class that tells its subclasses "you should ALL have some way of keeping state for X but I (the base class) will not modify that X state, in which case you should make an abstract method in order to convey that message, something like this:
public abstract class Super {
protected abstract Object getMyField();
}
It's hard to say with such a vague description, but it would seem like you could do some generalization and push some common code up into your superclass. If your subclasses are doing something similar with the field then some commonality could be found (using template methods or strategies to handle subclass-specific differences), otherwise if every subclass is doing something different with it then what's the point of using a common field?
No, I don't think so. Abstract class serve that purpose (Have common functionality in base class and let subclass implement only specific required functionality).
So, if you don't use that field in class Super - why do you need it there?
Perhaps your super class would provide an interface to interact with this field in generic way, for example:
public abstract class Super<T> {
protected T myField;
public T getField() {
return myField;
}
}
public class Child extends Super<String> {
public Child( String label ) {
super.myField = label;
}
}
As stated in this tuturial
A protected field or method is accessible to the class itself, its subclasses, and classes in the same package.
This means that the protected fields have been designed precisely to have these characteristics.
Just on a lighter note The only thing common in your hirarchy is one field then you should get rid of abstract class and Create one Marker Interface.
So I have a parent class, here refered to as A, and class B which extends A.
public class A
{
private int a = 1;
public int getA()
{
return a;
}
}
public class B extends A
{
private int a = 2;
}
However, when B.getA() is called, it returns 1 from class A instead of the 2 in class B. Did I do something wrong? Because I had a similar problem a couple of months ago, and it miraculously worked after a lot of messing around. The only difference is that the method deals with adding an object to an ArrayList.
Thanks.
Private variables are private even to subclasses. A.a and B.a are two completely different fields. If you want to change data in a subclass, make it a protected field or (better yet) add an optionally abstract getter to the parent class and override it in the subclass.
The reason is that the fields defined in a class are never overriden in subclasses, irrespective of the fields' access modifiers.
If you declare a field in a subclass with the same name as a field in the superclass, your subclass actually has two fields with that name. The field inheritted from the superclass is hidden in the subclass, but (if the access rules permit it) the superclass version can be accessed in the subclass; e.g. by qualifying the field name with the class name.
(In your particular example, the access rules forbid B to access the a declared in A. A private field or method can only be accessed from the class itself or nested classes. But even so, there are two fields called a in any B instance instance.)
I want to pass an instance of a super class to a constructor of a sub class. My first idea was to swap the instance of the super class in the sub class similar to javascripts prototypes, but I was told here that Java does not support swapping the reference of the super instance because there is no super instance per se.
To circumvent this issue I want to use a copy constructur which accepts a super class instance. Then I will have to relink all references manually which on the long run will invite bugs when other people extend the code of the super class and forget the copy constructur in the sub class.
Question: Is there some neat and nice way to copy all references automatically, maybe with some reflection mechanism to prevent future bugs?
You shouldn't copy all the references from the superclass instance to the subclass instance. BTW, all these references should not even be accessible from the subclass, if they are declared as private fields in the superclass (as they should be, generally).
What you probably need is delegation, instead of inheritance:
// Foo is the superclass
private class FooAdapter {
private Foo foo;
public FooAdapter(Foo foo) {
this.foo = foo;
}
public void doThis() {
return foo.doThis();
}
}
FooAdapter could extend Foo or (better) theyr should implement a common interface, but that's not necessarily needed.
If this doesn't answer your problem, please tell us what you want to do, instead of telling us how you want to do it. What's the problem you want to solve?