Final variables in abstract classes - java

In Java, I can't create instances of abstract classes. So why doesn't eclipse scream about the following code?
public abstract class FooType {
private final int myvar;
public FooType() {
myvar = 1;
}
}

The code is fine, the final variable is initialized in the constructor of FooType.
You cannot instantiate FooType because of it being abstract. But if you create a non abstract subclass of FooType, the constructor will be called.
If you do not have an explicit call to super(...) in a constructor, the Java Compiler will add it automatically. Therefore it is ensured that a constructor of every class in the inheritance chain is called.

You can have constructors, methods, properties, everything in abstract classes that you can have in non-abstract classes as well. You just can't instantiate the class. So there is nothing wrong with this code.
In a deriving class you can call the constructor and set the final property:
public class Foo extends FooType
{
public Foo()
{
super(); // <-- Call constructor of FooType
}
}
if you don't specify a call to super(), it will be inserted anyway by the compiler.

You can create concrete sub-classes of FooType and they will all have a final field called myvar.
BTW: A public constructor in an abstract class is the same as a protected one as it can only be called from a sub-class.
What is your doubt?

Ok. See, an abstract class can have a constructor. It's always there-implicit or explicit. In fact when you create an object of a subclass of an abstract class, the first thing that the constructor of the subclass does is call the constructor of its abstract superclass by using super(). It is just understood, that's why you don't have to write super() explicitly unless you use parameterized constructors. Every class even if it is abstract, has an implicit constructor which you cannot see. It is called unless you create some constructor of your own. so long you created abstract classes without creating any custom constructor in it, so you didn't know about the existence of the implicit constructor.

You definitely can declare final variable in abstract class as long as you assign value to it either in the constructor or in declaration. The example that guy gave makes no sense.

No you can't declare final variables inside an Abstract class.
Check Below example.
public abstract class AbstractEx {
final int x=10;
public abstract void AbstractEx();
}
public class newClass extends AbstractEx{
public void AbstractEx(){
System.out.println("abc");
}
}
public class declareClass{
public static void main(String[] args) {
AbstractEx obj = new newClass ();
obj.AbstractEx();
// System.out.println(x);
}
}
This code runs correct and produce output as
abc
But if we remove comment symbol of
System.out.println(x);
it will produce error.

Related

What does "extends" actually do?

I am currently studying the concept of "class abstraction" and "extension" and have been wondering:
"If I declare a parametrized constructor inside my abstract class why won't extension on another class work unless I declare myself the constructor with the super keyword invoking the parameters of the abstract class's constructor?"
I understand the fact that extension instances the previous abstract class into the extended one and tries to call the default constructor but have been wondering why it gives out an error.
Is it because the constructor has been parametrized or simply because the empty constructor does not exist?
Does the extends keyword call something along the lines of this?
Object myClass = new AbstractClass();
And the missing parameters are the reason why it gives out an error so something along the lines of this would be correct
Object myClass = new AbstractClass(int foo,float boo);
And if that is it, does the super keyword essentially, if you'll allow me the term, "put" the parameters given in the parenthesis "inside" the constructor?
If that's not it what am I getting wrong? How does it actually work?
You should think of the extends keyword, in this context, as just saying that a class is the subclass of another class, and does nothing else. And that there are rules governing how subclasses and superclasses should work.
When you construct a subclass, you must construct its superclass first. For example, to create a Bird, you must first create an Animal. That makes sense doesn't it? To demonstrate this in code:
class Animal {
public Animal() {
System.out.println("Animal");
}
}
class Bird extends Animal {
public Bird() {
System.out.println("Bird");
}
}
Doing new Bird() will first print Animal and then Bird, because the Animal's constructor is called first, and then the Bird constructor. So actually, the Bird constructor implicitly calls the superclass' constructor. This can be written as:
public Bird() {
super();
System.out.println("Bird");
}
Now what happens if the super class does not have a parameterless constructor? Let's say the constructor of Animal now takes a String name as argument. You still need to call the superclass' constructor first, but super() won't work because super() needs a string parameter!
Therefore, the compiler gives you an error. This can be fixed by calling super() explicit with a parameter.
"If I declare a parametrized constructor inside my abstract class why
won't extension on another class work unless I declare myself the
constructor with the super keyword invoking the parameters of the
abstract class's constructor?"
Because the super class says that it MUST be constructor using that declared constructor and there is no other way around. This applies to every extending class - required constructor must be called.
The same happens with any class when you declare other constructor than default one. For example, having
public class A{
//no default no-arg ctor here
public A(String name){
....
}
}
public class B{
//default no-arg ctor will be created
}
so then
B b=new B();
A a=new A(); //// INVALID!
A a=new A("foobar"); // yeah that is it
The same applies when you are extending classes. To construct child instance, you must first "internally create parent instance" calling super.constructor. Since there is no default constructor, ANY of explicit declared superconstructors must be used.
When initializing an Object the constructor will always be called. Even if you do not define one constructor there will be a default one without any parameters. So if you define a constructor in the abstract class, you have to call that constructor with super().
If you do not define any constructors, then it will be implicitly called as the default one.
If I declare a parametrized constructor inside my abstract class why won't extension on another class work unless I declare myself the constructor with the super keyword invoking the parameters of the abstract class's constructor?
There is no default constructor available in AbstractClass since you define a parametrised constructor. If you don't define a constructor yourself, a default constructor without arguments is implicitly created. You can manually add such one now or you need to use the only available constructor (which is parametrised) with super().
Example of your code with defining constructor without arguments:
class AbstractClass {
AbstractClass() {} // added manually since not created implicitly
AbstractClass(int foo, float boo) {}
}
class RealClass extends AbstractClass {
RealClass() { } // calls super() implicitly
}
AbstractClass myClass = new RealClass();
Example of your code with calling super() with arguments:
class RealClass extends AbstractClass {
RealClass() {
super(1, 2);
}
}
class AbstractClass {
AbstractClass(int foo, float boo) {}
}
AbstractClass myClass = new RealClass();

Can I know the extending class from the super class in Java?

I have the following classes.
public class Super{
public static void useSubClass(){
//I want to access the sub class object here, how.
}
}
public class Sub1 extends Super{
}
public class Sub2 extends Super{
}
I want to access the sub-class object from a static method in super-class. i.e. When I call Sub1.useSubClass() the method has access to Sub1.class and when I use Sub2.useSubClass(), I can access the Sub2.class.
Is there any way to access the sub-class object from super-class.
In general, you cannot do that from a superclass (and shouldn't!) because you won't know (and shouldn't assume anything about!) what classes will inherit from your superclass.
Depending on exactly what you want to do, there are alternatives, such as:
Use the template pattern to define "filler methods" that your subclasses must implement; these filler methods will be called by the template method in your superclass.
Define methods to be overridden by your subclass.
Define interfaces to be implemented by your subclass.
Update: As #JB Nizet has pointed out, I might have misread the question.
Here's something (very similar to the Observer Pattern) you can do if you wish to access subclasses from the static method in your superclass:
Define a static listener list in your superclass, call it List observerList
In the constructor of your superclass, add the class instance itself to that static observerList
For all subclasses, it is their responsibility to call super() from their constructors in order to register themselves to observerList (and unregister in deconstructor)
Then in your superclass's static useSubClass() method, you can iterate through that list of subclass instances, find the particular one you care about (maybe specified by some argument), and then do something with it.
Static methods are not inherited, and calling Sub2.useSubClass() is strictly equivalent to calling Super.useSubclass().
There is no way to get this information, because it doesn't exist. The compiler allows calling Sub2.useSubclass(), but translates it into Super.useSubclass().
public static void useSubClass(Super sub) {
if (sub instanceof Sub1) {
// Do something
} else if (sub instanceof Sub2) {
// Do something else
} else {
// Something else is extending Super
}
}
However, a better question is why? Can't you simply override the method in your subclass?
No you cannot because the super-class cannot know the methods of the sub-classes.
You should consider to create a new class which sees both super-class and sub-classes and implement the static method inside this new class
For the record, you could do this in Python, using class methods:
class super(object):
#classmethod
def usesubclass(cls):
print cls
class sub1(super):
pass
class sub2(super):
pass
Using this code, you could call sub1.usesubclass() or sub2.usesubclass(), and that would print the representations of the sub1 and sub2 classes, respectively:
>>> sub1.usesubclass()
<class '__main__.sub1'>
>>> sub2.usesubclass()
<class '__main__.sub2'>
Java, however, does not support such mechanisms, unfortunately. When you compile Sub1.useSubClass() in your example, the compiler will simply use Sub1 as the basic namespace to look up the the useSubClass() method in Super, but no information on that is actually compiled into code. In the resulting bytecode, the call is simply one directly to Super.useSubClass() and nothing more.
I sympathize with your plight, but Java is what it is. The closest thing you could come, I think, would be the following code:
public class Super {
public static <T extends Super> void useSubClass(Class<T> sub) {
}
}
And then call that method explicitly as either Super.useSubClass(Sub1.class) or Super.useSubClass(Sub2.class).
I figured something out. It works if implemented with care.
/** SuperClass.java **/
public abstract class SuperClass {
public static void printClass(){
System.out.println(new ImplementingClassRetriever().getCallingClass());
}
static class ImplementingClassRetriever extends SecurityManager{
public Class getCallingClass() {
Class[] classes = getClassContext();
for (Class clazz : classes) {
if (SuperClass.class.isAssignableFrom(clazz) && clazz != null
&& !clazz.equals(SuperClass.class)) {
return clazz;
}
}
return null;
}
}
}
/** Main.java **/
public class Main{
public static void main(String[] args) {
Sub.printClass(); //this does not work
Sub.testStaticCall(); //this works!! :)
}
}
class Sub extends SuperClass{
public static void testStaticCall(){
Sub.printClass(); //calling the method in the super class
}
}
This is just a toy example. The super class contains a static class that contains a method to retrieve the calling class.
In the subclass I have another static method which calls the superclass's method for printing the class name.
The Main class/function contains two calls to Sub's inherited and locally implemented method. The first call prints null, because the calling context (i.e. Main) is not a subclass of Super However the delegate method in Sub works because the calling context is now a subclass of SuperClass and hence the calling class can be determined.
Although You can create a reference to the super class and point it to any sub-class. This can also be done dynamically during run-time. This is a way of run-time polymorphism.

Why does a Java constructor have to be public or protected for a class to be extended outside its package?

The following is my ProtectedConstructor.java source code:
package protectCon;
public class ProtectedConstructor{
public int nothing;
ProtectedConstructor(){
nothing = 0;
}
}
And following is the UsingProtectedCon.java source:
package other;
import protectcon.ProtectedConstructor;
public class UsingProtectedCon extends ProtectedConstructor{ //**Line 4**
public static void main(String... a) {
}
}
When I compile UsingProtectedCon.java, I get error at Line 4 shown above. It says that ProtectedConstructor() is not public ; so cannot be accessed outside package.
However, since my class is public, shouldn't I be able to extend it outside package. I am anyway not creating any instance of it.
Now, if I make the constructor of ProtectedConstructor class as public or protected then the code compiles fine with no error.
So then why is it necessary even for the constructor to be public or protected, and not just have default access?
If you want to extends a class outside its package it must have a constructor that is public or protected because in Java every constructor must call a constructor from its superclass.
Because of this there is an implied super() call in every constructor which does not have this() or an explicit call to super() as its first statement. And if you don't specify a constructor at all Java will add a default parameterless constructor, so in effect your code looks like this:
public class UsingProtectedCon extends ProtectedConstructor {
public UsingProtectedCon() {
super();
}
public static void main(String... a) {
}
}
So in other words your code is failing to compile because the call to super() in the default constructor cannot be resolved.
constructor is a member of class like field and method so access modifier applies to it in the same manner it apples to all the member of class
when you extend the class A in B , A's its default constructor will get called from B's constructor implicitly (if you don't call any of the overloaded constructor)
in your class ProtectedConstructor is defined with Package-Private access
This means that outside the package its not seen even by the classes that extend from your ProtectedConstructor class
Define your constructor with 'protected' access modifier instead and you'll be done:
package protectCon;
public class ProtectedConstructor{
public int nothing;
protected ProtectedConstructor(){
nothing = 0;
}
}
Your constructor is not public. Default scope is package-private.
JLS 6.6.7 answers your question. A subclass only access a protected members of its parent class, if it involves implementation of its parent. Therefore , you can not instantiate a parent object in a child class, if parent constructor is protected and it is in different package.Since the default constructor of the subclass would try to call parent class constructor ,you got this error.
See this SO Post for details
to avoid all confusion do it like this.
package protectCon;
public class ProtectedConstructor{
public int nothing;
public ProtectedConstructor(){
nothing = 0;
}
}
package other;
import protectCon.ProtectedConstructor;
public class UsingProtectedCon extends ProtectedConstructor{ //**Line 4**
public UsingProtectedCon(){
super();
}
public static void main(String... a){
}
}
You can have constructors which are public, protected (for internal used) and even private.
A simple example is String which has public constructors for general use and package-local constructors for internal use.
The ObjectOutputStream class has a public constructor which takes an OutputStream and a protected constructor which can only be used by a sub-class.
BTW: if you have an abstract class, does it make sense to make the constructor public as if often the case. ;) hint: it is the same as protected.
If child will have constructor which is private in parent,we can make child's instance with that constructor and cast it to parent's type.
So to prevent this java compiler is not allowing constructor to have constructor which is private in parent.

Can I access static member variables defined on the subclass from a method on the abstract superclass?

I have an abstract class with a single concrete method. In this method I want to use a static class variable from the classes that derive from the one the method is declared in. To do so, I of course have to declare this static variable in the abstract class as well.
When the method is called, the variable is resolved to the one in my abstract base class as opposed to the one in the derived class. Do I need to decorate the derived class' property with an attribute?
Am I trying to do something that is not supported in Java, or am I just missing something?
You're trying to do something that isn't supported. Fields can't be "overridden" - and static members don't behave polymorphically.
Instead, create abstract properties which can be implemented in the derived classes. They'll have to be instance properties even if they return static variables.
You can't override variables, only methods. If its likely that a subclass needs to give a different value, add a getter method to the class that does that.
abstract class Foo {
static private final String someValue = "blah";
String getSomeValue() {
return someValue;
}
public abstract void someMethod();
}
class Bar extends Foo {
String getSomeValue() {
return "somethingElse";
}
public void someMethod() {
String x = getSomeValue();
}
}
Depending on what you want to do, you can do:
Base b = new Sub();
System.out.println(b.myInt); // will print myInt from Base
Sub s = new Sub();
System.out.println(s.myInt); // will print myInt from Sub
, but you likely want Jon's approach.

How to create an "abstract field"?

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.

Categories

Resources