I'm having a little trouble with inheritance. What i have done is made a superclass as some of the attributes in the subclasses were identical.
I am trying to reference the superclass, I tried putting super(name); above the line name = replacementName; it will not compile saying name has private access in the Superclass 'person'. I know that it won't access a private field but how can I get the name from the superclass in a subclass method?
Here is the method.
public void changeName(String replacementName){
name = replacementName;
}
Help appreciated.
You have several options :
1 - In your super class, use private declaration for the name attribute and add public (or protected) getters/setters. Then you can modify your super class field from your child class using the setter method.
2 - In your super class, use protected declaration for your name field. Then you can access it directly from your child class.
...
Related
If base class and derived class have same field name, then we use super keyword to access base class field. But in case of multilevel inheritance and there also in every class has same field name, how to access field name of super class in child class.
class GrandParent {
String name;
}
class Parent extends GrandParent {
String name;
}
class Child extends Parent {
String name;
//now here, how to access GrandParent name field
}
There is no multiple inheritance here. Your snippet demonstrates field hiding.
Within a class, a field that has the same name as a field in the superclass hides the superclass's field, even if their types are different. Within the subclass, the field in the superclass cannot be referenced by its simple name. Instead, the field must be accessed through super.
super allows you to see members only on one level down (=members of the direct parent). Chains like super.super are considered syntactically invalid.
But there are at least two ways to achieve what you want:
(GrandParent)this).name - upcasting to GrandParent
GrandParent.class.getDeclaredField("name").get(this) - extraction by reflection
Why does Java disallow inheritance from a class whose constructor is private?
Java doesn't prevent sub-classing of class with private constructors.
public class Main {
static class A {
private A() {
System.out.println("Subclassed A in "+getClass().getName());
}
}
static class B extends A {
public B() {
}
}
public static void main(String... ignored) {
new B();
}
}
prints
Subclassed A in Main$B
What it prevents is sub-classes which cannot access any constructors of its super class. This means a private constructor cannot be used in another class file, and a package local constructor cannot be used in another package.
In this situation, the only option you have is delegation. You need to call a factory method to create an instance of the "super" class and wrap it.
Because a class must call its super class constructor always. If the super class constructor can't be accessed, then the sub class can't be initialized.
More info: JLS 8.8.10. Preventing Instantiation of a Class
Regarding Brian Roach's comments:
The call [to the parent class constructor] is only implicit if you don't do it explicitly and the parent has a public or protected no-arg constructor (or hasn't defined any in which case there's a default no-arg). It's required because ... that's how the language works. Children [classes] must call [their] parent's constructor.
Note that when you instantiate any class in Java, there's always a implicit call to Object constructor since it is the super class of all classes. It will execute its default constructor:
public Object() {
}
Note from the JLS link:
It is a compile-time error if a default constructor is implicitly declared but the superclass does not have an accessible constructor (§6.6) that takes no arguments and has no throws clause.
If constructor of a class is private then child class cannot make call to super constructor.
Hence inheritance would fail.
If you have a subclass, you have 2 possiblities for child class(subclass) constructors :
1. Default Constructor(No argument constructor) : In this case default constructor will automatically try to call the parent class constructor : this will fail since parent class constructor is private.
2. Parameterized Constructor : When you try to create an object for a child class which has parameterized constructor, you need to mandatorily call parent class constructor from child class constructor by either passing parameters or not passing parameters : this will also fail since parent constructor is private.
Since child class will have either default constructor or parameterized constructor and its not possible to have either of them, you cannot have a subclass for a parent class with private constructor.
Yes adding something to Luiggi's answer this feature of java is used when creating the Singleton classes which allows only one instance of that class to be created.
This is because, When we do inheritance the job of the compiler is to make a direct or indirect relation of all the classes with the Object class by writing the super() at the very first statement of every class constructor .
when we make the constructor as private that means it shouldn't be accessed from outside the class but when we do inheritance compiler will implicitly write this type of statement.
class SubClassName extends SuperClassName {
public SubClassName() {
super(); // which will indirectly going to call the Parent class constructor from outside its scope
}
}
I am a noob and I need some help.
So I have this abstract class with a private variable. I also have a method named getThing() to return that.
I have a class that extends that abstract class, and it too has a private variable and a method that overrides the original to get the value from the abstract class.
Well the only way to be able to access both values is by creating a second method in the subclass called getSuperThing, and using the super in that. Well I was just wondering out of curiosity if there was some easier way to do that and be able to access the abstract classes method by doing something like objectNae.super.getThing().
Thanks ;)
The variable is private and so can only be referenced by the containing (abstract) class. As you have stated, from a subclass, you can invoke the superclass method (rather than the overridden one).
If you want to make the variable accessible from the subclass directly (without requiring the accessor method), make it protected instead. Here is the documentation on Controlling Access to Members of a Class.
If I understand your question correctly, then you just shouldn't override the abstract class' method in the concrete subclass. No need to, unless you need the subclass to return a different value than that returned by the abstract class (and that would suggest poor design).
Rather, the abstract class' method will be accessible as a method of the subclass.
So, if you have:
public abstract class AbstractClass {
private int value = 3;
public int getValue() {
return value;
}
}
public class ConcreteClass extends AbstractClass {
}
then you should be able to do:
new ConcreteClass().getValue()
I don't think you have other ways than calling super.getThing() in the subclass's getThing() or getSuperThing() method. Abstract class must be subclassed before being used.
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.)
The Oracle Java tutorial site has this paragraph that is confusing me:
All classes have at least one
constructor. If a class does not
explicitly declare any, the Java
compiler automatically provides a
no-argument constructor, called the
default constructor. This default
constructor calls the class parent's
no-argument constructor, or the Object
constructor if the class has no other
parent. If the parent has no
constructor (Object does have one),
the compiler will reject the program.
If all objects directly or indirectly inherit from Object how is it possible to elicit the compiler rejection spoken of? Does it have to do with the constructor being private?
If all objects directly or indirectly inherit from Object how is it possible to elicit the compiler rejection spoken of?
I think the basis is of your misunderstanding is that you are thinking that constructors are inherited. In fact, constructors are NOT inherited in Java. So consider the following example:
public class A {
public A(int i) { super(); ... }
}
public class B extends A {
public B() { super(); ... }
}
The class A:
does not inherit any constructors from Object,
does not explicitly declare a no-args constructor (i.e. public A() {...}), and
does not have a default constructor (since it does declare another constructor).
Hence, it has one and only one constructor: public A(int).
The call to super() in the B class tries to use a non-existent no-args constructor in A and gives a compilation error. To fix this, you either need to change the B constructor to use the A(int) constructor, or declare an explicit no-args constructor in A.
(Incidentally, it is not necessary for a constructor to explicitly call a superclass constructor ... as I've done. But a lot of people think it is good style to include an explicit call. If you leave it out, the Java compiler inserts an implicit call to the superclasses no-args constructor ... and that results in a compilation error if the no-args constructor does not exist or is not visible to the subclass.)
Does it have to do with the constructor being private?
Not directly. However, declaring a constructor private will prevent that constructor being called from a child class.
The key thing to understand is that the no-arg constructor will only be automatically generated if the class doesn't already have a constructor.
It's thus easy to create a class that doesn't have a no-arg constructor.
The simplest way to think of this problem is as follows:
The non-args constructor is provided as the default constructor by Java for any class you create.
The moment you create a custom constructor with arguments, Java says “hey, this class has got a custom constructor, so I am not going to bother creating/supplying the default non-args constructor!”
As a result now your class does NOT has the default non-args constructor.
This means when you create a subclass, based on your class, you need explicitly call the arguments based custom constructor that you created.
If you have a sub-class of a sub-class
class A
{
A(int i) {..}
}
class B extends A
{
}
Here the default constructor inserted into B will try to invoke A's no-argument constructor (which doesn't exist) as it only has a constructor taking one argument
The immediate superclass of the object must have a protected or public constructor (or no constructor at all, in which case one will be created). So, if I create a class that extends Object, with a private constructor only, then nothing will be able to extend my class.
Yes. A private contructor is a special instance constructor. It is commonly used in classes that contain static members only. If a class has one or more private constructors and no public constructors, then other classes (except nested classes) are not allowed to create instances of this class.
The declaration of a private constructor prevents the automatic generation of a default constructor.
EDIT:
A class defined within another class
is called a nested class. Like other
members of a class, a nested class can
be declared static or not. A
nonstatic nested class is called an
inner class. An instance of an inner
class can exist only within an
instance of its enclosing class and
has access to its enclosing class's
members even if they are declared
private.
What this means is that if you inherit from a line of class(es) that make the default no-arg constructor private (or it does not exist, for example), your sub-classes must declare a constructor in line with its parent's alternative constructor.
For example, the following declaration of Bar is not allowed:
public class Foo {
private Foo() { } // or this doesn't even exist
public Foo(int i) {
}
}
public class Bar extends Foo {
}
Let me append to all aforementioned one more interesting case where the default/no-arg constructor is infeasible, in the sense that unless it is explicitly declared, the compiler cannot assume it and yet it has nothing to do with subclassing. This is the case of having a class with a final field which expects a constructor to initialize it. For example:
class Foo extends Object {
private final Object o;
public Foo(Object o){
this.o = o;
}
}
Here it's easy to see that an instantiation of a Foo-object requires the initialization of the final field o so any invocation of Foo() - directly or not - is doomed to failure... Let me underline that the no-arg constructor in the super class (Object) exists and is publicly accessible but it is the presence of the final field (o) that deactivates it in Foo.