public class ExtAA extends AA {
static int iTime;
public static void main(String argv[]) {
ExtAA d = new ExtAA();
d.func(iTime);
}
public static void func(int iTime) {
System.out.println(iTime);
}
public ExtAA() { }
}
class AA {
public AA() { System.out.println("AA"); }
}
prints:
AA
0
I would have expected public ExtAA() { } to override the constructor for AA and thus not print AA, just 0. Could someone explain in what way I am wrong, and if I'd want to override the constructor how could I ?
P.S. It is completely possible that my question is stupid, but I don't get what public ExtAA() { } should or could do. This was at a test, I messed up and I'd like to know what's actually happening (yes, I did go into debug and go over it step by step, I just don't know why new ExtAA uses AA instead of it's own defined constructor)
Constructor of super class in Java is always called. You can't stop that. You can just control which constructor is called if there are more of them.
Please consider reading some basic tutorial of Java, this is elementary thing of Java OOP.
Implicitly your constructor looks like this:
public ExtAA() {
super(); // Constructor of super class call, always first line of code in child constructor
}
An object has the fields of its own class plus all fields of its parent class, grandparent class, all the way up to the root class Object. It's necessary to initialize all fields, therefore all constructors must be called! The Java compiler automatically inserts the necessary constructor calls in the process of constructor chaining, or you can do it explicitly.
Imagine if you could skip a constructor from a base. It could leave the parent part of an object in an extremely unstable state.
Think about a situation where a base class does some kind of meaningful initialization in the constructor. If that doesn't get done, then suddenly the base class part of your object is in crazy-town. This is almost certainly why Java decided to work like this.
As a super trivial example, imagine if you had a SortedArrayList class that extends ArrayList. If SortedArrayList somehow didn't call any of the ArrayList constructors, do you think the internals of the object would make sense? Somewhere there would be a nulled out data structure meaning things would crash and burn. In certain situations it might make sense to override a constructor, but apparently the Java people felt that the risk of accidentally doing it wasn't worth the ability (and it very rarely makes sense in a well designed class graph -- if the child class doesn't depend on the base class in some way, then why is it a child class to begin with?).
Related
I am 70% confident that this is impossible, but is there a way to make sure that subclasses have a particular constructor or factory method?
In this case, I am trying to create a StringSerializable that would require subclasses to have the following methods
toString, which converts the object to a String.
fromString, which gets an instance from a String.
Obviously, in the first case, I can just make toString abstract. On the other hand, having a nonstatic fromString seems to be problematic. However, I can't create an abstract static method. I also do not think that a constructor is entirely appropriate.
You're correct; it's impossible to force it at compile time. There are various tricks you could do at runtime (such as using reflection in tests), but that's about it.
But ask yourself: why do you want to require that? You can't dynamically invoke a static method or constructor (except through reflection), so how exactly would you use those required factories, if you had them?
If it's just for consistency in the code (which is a good thing!), then you'll just have to ensure that consistency as you develop the code base. A comment in the base class can go a long way here, as can code reviews and other "soft" techniques.
If you plan to use the factories in reflection, then similar reflection can be used in tests to make sure that each subclass has the bits it needs.
Another option is to create a non-static factory:
public interface FooMaker() {
Foo create(String arg);
}
... and use that, rather than a static fromString method.
There again you have the same problem of "how do I ensure that every subclass has a FooMaker implementation?" and again I would say that you shouldn't worry about that. If you make the FooMaker the "starting point" of your code, rather than the subclasses, then it doesn't matter what the subclasses are doing; all that matters is that your FooMakers give you a way of going from string to Foos, and each Foo has a way of going back to a string.
the following code does ensure that every subclass needs to implement the static method, if the subclass does not implement the method it will fail when classes are constructed, as close as you can get to a compile time error, but not at compile time
the exception thrown is very clear and the programm will instantly fail when started
public abstract class Base {
static Functional test;
static {
if(test == null) {
throw new RuntimeException("You need to provide an implementation for the implemntMe method in class base");
}
}
private interface Functional {
Base implementMe(int whatever, boolean anotherParameter);
}
public static void main(final String[] args) {
}
}
the private interface construct ensures that only lambdas can be used to implement the method
a subclass would have to look like this
public SubClass extends Base {
static {
test = (int whatever, boolean anotherParameter) -> {
Subclass tmp = new Subclass();
//construct object
tmp.setWhatever(whatever);
return tmp;
}
}
}
lamdas are like inline methods that implement a functional interface, an interface which has only one abstract method
you can also declare the interface publicly at any other place and implement it with an anonymous inner class,
but my way makes sure that programers have to copy and paste code to reuse it,
or need to copy the object of Functional from another class
Is calling super() constructor should be the very first line of the constructor? If so then why? Why can't I do some simple limited calculations before constructor call, for example, constructor parameters calculation?
I found a situation with inner class constructors which can be called with closure specification:
class A {
class Inner1 {
Inner1() {
// do something
}
}
}
class B {
A a1 = new A();
A a2 = new A();
class Inner2 extends A.Inner1 {
Inner2(boolean sel) {
(sel?a1:a2).super();
}
}
}
This case shows we can want to select enclosing instance for a base class constructor. Why selection logic should be so limited? Why one can't write something like this
if( sel ) {
a1.super();
}
else {
a2.super();
}
ADDITION
By my question I mean that the limitation could be like in the following case:
public class Base {
private final String content;
public Base(String content) {
this.content = content;
}
public String getContent() {
return content;
}
}
public class Derived extends Base {
public Derived(String content) {
super(String.format("Current value of content is %s.", getContent()));
}
}
In latter case I:
1) Fulfilling the requirement of super() to be in the first line
2) Violating the order of construction
3) Get a compiler error "Cannot refer to an instance method while explicitly invoking a constructor"
So, why we can't abolish "first line requirement" and rely only on errors like the last one?
Yes, a call to super() is required as the very first call in a constructor.
So much so that if you leave it out the compiler will (attempt to) insert the call for you. To understand the why, you would need to understand the philosophies of Java's designers. Gosling has always been in the camp of computer scientists that believe that accessing partially initialized objects is one of the bigger sources of bugs in computer programs. And as such he designed a strict initialization hierarchy that would help to alleviate this problem. Wether you agree with the philosophy is moot - but its important to realize that its as important a concept in Java as for example, references vs pointers, or real, bounded arrays. It should be noted that even languages like Objective C that allow you to invoke initialization at any time, go to great length to enforce initialization chaining, except that they need to do so via convention, as opposed to strict language rules.
I'm not sure what you were trying to illustrate in your example - but after years of development with Java I doubt you will find many cases where you really need to perform logic before invoking super.
Constructor calls are chained with super of every class in hierarchy being invoked before constructor of that class is invoked. As all classes in Java inherited from object class, so constructor of Object class is invoked first for every class with reason being that memory allocation for object is done by constructor of Object class
I have the following example classes in Java:
public class A { }
public class Super {
protected Super() { }
public Super(A a) { }
}
public class Sub extends Super { }
public class Consumer {
public Consumer() {
Sub sub = new Sub(new A()); //compiler error
}
}
The compiler error states that the arguments cannot be applied to the default constructor in Sub, which is perfectly understandable.
What I'm curious about is the rationale behind this decision. Java generates the default empty constructor in Sub; why can't it call it behind the scenes in this case? Is this primarily a case of sane hand-holding, or is there a technical reason?
EDIT
I'm aware that this is a language limitation. I'm curious about why it is a language limitation.
EDIT 2
It seems that, as is often the case, I was too close to the code I was actually working in to see the big picture. I've posted a counter-example in the answers below that shows why this is a Bad ThingĀ®.
I think it's an issue of both readibility and not assuming intent. You say
Java generates the default empty constructor; why can't it call it behind the scenes in this case?
Yet to me, it would make much more sense for Java to implicitly call the Super(A) constructor "behind the scenes" than to call the Super() constructor, disregarding A.
And there you have it. We already have two disparate assumptions about what should (or could) happen in this case.
One of the Java language's core principles is transparency. As much as possible, the programmer should be able to see by looking at the code what will happen, sometimes at the expense of convenience or magic at the syntax level.
A parallel tenet to that is not assuming intent: in cases where the programmer's intentions seem ambiguous, the Java language will sometimes favour a compile error rather than automatically chosing a default through some (arbitrary or otherwise) selection algorithm.
public class Sub extends Super { }
does not have the constructor Sub(A a), it only has the default constructor Sub().
Constructors are not inherited.
Base classes need to call super constructors in order to ensure an object is properly instantiated. For instance consider:
class Super {
final String field1;
public Super(String field1) {
this.field1 = field1;
}
...
}
class Base extends Super {
final String field2;
public Base(String field2) {
this.field2 = field2;
}
...
}
Does Base's constructor override the Super constructor? If so, then field1 is no longer guaranteed to be initialized, making inherited methods behave unexpectedly.
The moment you add a non-default constructor to the subclass then inherited constructors stop working. I think it'd be a confusing and rarely useful feature it was added to the language, although technically I can see no reason why it wouldn't be possible.
You've overidden the default public constructor, so there isn't anything to call.
So the class Sub is equivalent to
public class Sub extends Super
{
protected Sub(){}
public Sub(A a) { }
}
It would because its
Sane behaviour - Behaves as specified by the programmer, and it also follows the concept of inheritance in OOP languages
Following its C++ legacy
I'm putting this out as a technical reason for this behavior; I'm in agreement with several other answers that this could be semantically confusing.
Consider the following example:
public class A { }
public abstract class Super {
protected Super() {
// perform time consuming, destructive, or
// otherwise one-time operations
}
public Super(A a) {
this();
// perform A-related construction operations
}
}
public class Sub extends Super { }
public class Consumer {
public Consumer() {
Sub sub = new Sub(new A());
}
}
When the Sub is constructed, in this case the default constructor on Sub would be called, which would chain to the default constructor on Super (because that's the magic the language defines). Then, the call to Super(A) would invoke logic that is designed to be run once, at construction. This is obviously not what the developer intends.
Even without the this() call in the Super(A) constructor, the developer's intention cannot be determined; the constructors may be mutually exclusive for some reason.
Polymorphism allows the programmer either to inherit, override or to overload an instance method of Parent Class.
But, it won't allow to make an instance method of parent class as more restrictive in child class. i.e it wont allow to use same name of parent class instance method, to declare as private in the child class.
Also JVM identifies the parent class version of an instance method, if child class didn't override it.
Similarly why don't JVM identifies the parent class version of an instance method, if the child class makes it more restrictive?
The more restrictive method of parent class in child class can be considered as child class specific method instead of overridden method by compiler.
This is all done in order to follow the Liskov Substitution Principle.
In order for inheritance in object oriented programming to behave as expected, a child class should be able to be substituted out for a parent class instance and not break a user of the class.
Making a child method more restrictive is basically saying "I don't want this method to be visible". Having the JVM automatically substitute out the parent class implementation in this case would just add a huge amount of confusion - just changing the call behavior might cause very unexpected behavior, even completely within the child class...
The more restrictive method of parent class in child class can be considered as child class specific method
Java authors could've implemented this. And many other things, like infamous multiple inheritance. But it would make language more complex for a very little benefit.
If you need a private version of parent's method, why don't you just give it different name? Since it'll be called from your child class only, there won't be much difference.
Java creators decided that Java should be as simple as possible, your question could cause problems with codes like this :
class A {
public void methodA(){
}
}
class B extends A {
#Override
private void methodA(){
}
}
//
public static void main(String... args){
A a = new B();
a.methodA(); // Should call the overridden method but as it's private it can't work.
}
You provided a solution for this case, but it as has a flaw :
class A {
public void methodA(){
}
public void methodB(){
methodA();
}
}
class B extends A {
#Override
protected void methodA(){
}
}
//
public static void main(String... args){
A a = new B();
a.methodB(); // Will methodA from A be called or from B ?
}
There the solution is complicated and against the java philosophy. That's more or less why the current solution is used; more simple even if a specific feature can't be used.
If I understand you correctly, you're saying that I should be able to write:
public class Foo
{
public int bar()
{
return 1;
}
}
public class Foo2 extends Foo
{
private int bar()
{
return 2;
}
public int barBar()
{
return bar();
}
}
public static void main(String[] args())
{
Foo2 foo2=new Foo2();
System.out.println(foo2.bar());
System.out.println(foo2.barBar());
}
Then if I create an instance of type Foo2 and call bar from within the class, it should call Foo2.bar so I should get back 2, but if I call bar from outside the class, it should call Foo.bar so I get back 1.
That is, the output of the above program should be:
1
2
Well, as this is a question about the design of the language, I guess the simple answer is, "Because that's how the designers of Java decided to do it."
The real question is, Why would you want it to behave the way you describe? Do you have an application where this would be useful? It seems to me that it would just be confusing.
What you want to do is wrap the "parent" class into another using composition, not inheritance when you want to restrict access.
So you create a new class having the class you want to wrap as member and provide access to what you want by designing your own API. Of course, you cannot use the new class in place ot the old one, but that wouldn't make any sense. If that is not want you want to do, I agree 100% with Reed Copsey's answer (I agree 100% even if that is what you wanted to do).
Referring here
A is a precompiled Java class (I also have the source file)
B is a Java class that I am authoring
B extends A.
How can logic be implemented such that A can call the methods that B has.
The following are the conditions:
I don't want to touch A(only as a
last option though that is if no
other solution exists).
I don't want to use reflection.
As stated, if needed I could modify A.
What could be the possible solution either way?
Class A should define the methods it's going to call (probably as abstract ones, and A should be an abstract class, per Paul Haahr's excellent guide); B can (in fact to be concrete MUST, if the method are abstract) override those methods. Now, calls to those methods from other methods in A, when happening in an instance of class B, go to B's overrides.
The overall design pattern is known as Template Method; the methods to be overridden are often called "hook methods", and the method performing the calls, the "organizing method".
Yes it seems that if you override the super/base-classes's functions, calls to those functions in the base class will go to the child/derived class. Seems like a bad design in my opinion, but there you go.
class Base
{
public void foo()
{
doStuff();
}
public void doStuff()
{
print("base");
}
}
class Derived extends Base
{
#Override
public void doStuff()
{
print("derived");
}
}
new Derived().foo(); // Prints "derived".
Obviously all of Derived's methods have to be already defined in Base, but to do it otherwise (without introspection) would be logically impossible.
I would be rather hesitant to do this. Please correct me if I am wrong and then I will delete, but it sounds like you want to maintain an A object along with a B object. If they indeed are not the same object, the "tying together" (that's a scientific term) you'll have to do would be pretty ugly.