I am trying to use a member variable called value in a subclass.
My super class is called SType and my subclass is called SResource.
I have a variable in the super class SType called value
I want this to be inherited by the subclass, how do I do this. The class looks like this
public class SType {
private String value;
public String getValue(){
return this.value;
}
public void setValue(String value){
this.value = value;
}
}
NOTE: I edited the question to make it more clear (given the comment below). Thanks it was a simple solution, just had to make the variable protected rather than `private
In order to access a superclass variable in a subclass, it has to be declared public or protected in the super class.
Maybe yours is private?
When you had private String value in the child class - this is a completely new variable - it's not the one from the parent class i.e. you have two distinct private variables (I am assuming the superclass one is private).
You can - make it protected instead of private.
instead of private try:
protected String value;
b.cos private can only access current class only.
while projected can access sub class
your question is appropriate but the meaning of private in the java meance to protect current variable or method from outside of the class.
Related
How is the compiler not complaining when I write the following code?
public class MyClass
{
private int count;
public MyClass(int x){
this.count=x;
}
public void testPrivate(MyClass o){
System.out.println(o.count);
}
}
Even though it is an instance of the same class in which testPrivate is written, shouldn't it give a compilation error at System.out.println(o.count)? After all, I am trying to access a private variable directly.
The code even runs fine.
A private member is accessible from any method within the class in which it is declared, regardless of whether that method accesses its own (this) instance's private member or some other instance's private member.
This is stated in JLS 6.6.1:
...Otherwise, if the member or constructor is declared private, then access is permitted if and only if it occurs within the body of the top level class (§7.6) that encloses the declaration of the member or constructor.
This feature of Java allows you to write methods that accept an instance of the class as an argument (for example - clone(Object other), compareTo(Object other)) without relying on the class having non private getters for all the private properties that need to be accessed.
Private fields are private to the class as a whole, not just to the object.
Other classes do not know that MyClass has a field called count; however, A MyClass object knows that another MyClass object has the count field.
Accessors are not security! They are encapsulation, to keep others from having to know about the code.
Consider if someone wrote a Quantum Bogo Sort, but disappeared once he quashed the last bug -- understanding the code causes one to be either deleted from the universe or to go mad.
Despite this minor drawback, if properly encapsulated, this should become your prefered sorting algorithm, as all fields and methods except Sort should be private.
You don't know how it works, and you don't want to know how it works, but it works and that's enough. If on the other hand, everything is public, and you have to understand how it does what it does to use it correctly -- that's just too much bother, I'll stick with quicksort.
Though it is the instance of the same class in which testPrivate is
written, but shouldn't it through a compiler error at
System.out.println(o.count);
No. It will never throw a compilation error.
This is much similar to what a simple getter and setter does or a copy constructor does. Remember we can access private members using this.
public MyClass {
private String propertyOne;
private String propertyTwo;
// cannot access otherObject private members directly
// so we use getters
// But MyClass private members are accessible using this.
public MyClass(OtherClass otherObject) {
this.propertyOne = otherObject.getPropertyOne();
this.propertyTwo = otherObject.calculatePropertyTwo();
}
public void setPropertyOne(String propertyOne) {
this.propertyOne = propertyOne;
}
public String getPropertyOne() {
return this.propertyOne;
}
}
Your testPrivate method accepts an instance of MyClass. Since testPrivate is a method inside MyClass, it will have access to private properties.
public void testPrivate(MyClass o) {
this.propertyOne = o.propertOne;
}
Methods defined inside the class will always have access to it's private members, through this. and instance variable.
But if you define testPrivate outside of MyClass then, you won't have access to private members. There you will have to use a method or a setter or a getter.
Methods, Variables and Constructors that are declared private can only be accessed within the declared class itself. Check the official documentation
How is the compiler not complaining when I write the following code?
public class MyClass
{
private int count;
public MyClass(int x){
this.count=x;
}
public void testPrivate(MyClass o){
System.out.println(o.count);
}
}
Even though it is an instance of the same class in which testPrivate is written, shouldn't it give a compilation error at System.out.println(o.count)? After all, I am trying to access a private variable directly.
The code even runs fine.
A private member is accessible from any method within the class in which it is declared, regardless of whether that method accesses its own (this) instance's private member or some other instance's private member.
This is stated in JLS 6.6.1:
...Otherwise, if the member or constructor is declared private, then access is permitted if and only if it occurs within the body of the top level class (§7.6) that encloses the declaration of the member or constructor.
This feature of Java allows you to write methods that accept an instance of the class as an argument (for example - clone(Object other), compareTo(Object other)) without relying on the class having non private getters for all the private properties that need to be accessed.
Private fields are private to the class as a whole, not just to the object.
Other classes do not know that MyClass has a field called count; however, A MyClass object knows that another MyClass object has the count field.
Accessors are not security! They are encapsulation, to keep others from having to know about the code.
Consider if someone wrote a Quantum Bogo Sort, but disappeared once he quashed the last bug -- understanding the code causes one to be either deleted from the universe or to go mad.
Despite this minor drawback, if properly encapsulated, this should become your prefered sorting algorithm, as all fields and methods except Sort should be private.
You don't know how it works, and you don't want to know how it works, but it works and that's enough. If on the other hand, everything is public, and you have to understand how it does what it does to use it correctly -- that's just too much bother, I'll stick with quicksort.
Though it is the instance of the same class in which testPrivate is
written, but shouldn't it through a compiler error at
System.out.println(o.count);
No. It will never throw a compilation error.
This is much similar to what a simple getter and setter does or a copy constructor does. Remember we can access private members using this.
public MyClass {
private String propertyOne;
private String propertyTwo;
// cannot access otherObject private members directly
// so we use getters
// But MyClass private members are accessible using this.
public MyClass(OtherClass otherObject) {
this.propertyOne = otherObject.getPropertyOne();
this.propertyTwo = otherObject.calculatePropertyTwo();
}
public void setPropertyOne(String propertyOne) {
this.propertyOne = propertyOne;
}
public String getPropertyOne() {
return this.propertyOne;
}
}
Your testPrivate method accepts an instance of MyClass. Since testPrivate is a method inside MyClass, it will have access to private properties.
public void testPrivate(MyClass o) {
this.propertyOne = o.propertOne;
}
Methods defined inside the class will always have access to it's private members, through this. and instance variable.
But if you define testPrivate outside of MyClass then, you won't have access to private members. There you will have to use a method or a setter or a getter.
Methods, Variables and Constructors that are declared private can only be accessed within the declared class itself. Check the official documentation
A question about inheritance in java...
class Base {
private int val = 10;
}
class Derive extends Base{
public void setVal(int value) {
super.val = value;
}
}
Since we can change the private field in super class using super keyword in the subclass, why should we use protected to declare fields in super class?
You can't do that. The code you've given doesn't compile, unless Derive is declared as a nested class within Base (which is a pretty rare case).
You should be getting an error like this:
error: val has private access in Base
Check your code you can never access private out side the class even if you have inherited that class.
super is an reference variable which is used to call parents constructor.
I've come across some odd behavior in assignment of final variables. You can assign a final varible in a constructor to initialize it, which makes sense. However you can't do the same in a subclass, even if the final variable is a member of the subclass -
public class FinalTest {
public final String name;
public FinalTest()
{
name = "FinalTest";
}
public static class FinalTestSubclass extends FinalTest {
public FinalTestSubclass()
{
name = "FinalTestSubclass"; //<---- this won't compile, assignment to final variable.
}
}
}
Can someone think of a good reason why this should/would work this way?
Every constructor of a subclass must invoke a constructor of the superclass as its first operation. Every final member variable must be initialized before a constructor completes. A final variable can be assigned only once. Given those rules, it is impossible for a subclass constructor to directly assign a value to a final superclass' member.
Making exceptions would increase complexity and create "gotchas" in exchange for limited additional utility.
A practical solution is to provide a superclass constructor that takes a value to be assigned to the final member. This can be protected or package-private if desired. If the superclass is outside of your control, there's a good chance that allowing derived classes to break its assumptions about the finality of its members would cause other problems.
If you were allowed to assign a value to name in FinalTestSubClass it would mean that the value assigned in FinalTest was not actually the final value.
If your example was valid, then this would mean that name could have different values (based upon which class was instantiated), making the final modifier pretty much redundant.
A better question is, why should the behavior you desire be allowed?
informally, final fields should have been initialized when the constructor is finished.
in your subclass constructor, super() has been called implicitly, the constructor of the super class is finished, the final fields in the super class should not be modified.
you may want this instead:
class A
final String s;
A(String s){ this.s = s; }
A() { this("default"); }
class B extends A
B(){ super("B's default"); }
This is standard behavior in Java
The key word final can by used in multiple way, for class close the possibility to inherite from it, for method to override it, for variable allow to be assigned only once in simply words.
For your case this variable is allready assigned in super class,
what You can do is
public class FinalTest {
public final String name = "FinalTest";
public FinalTest()
{
}
public static class FinalTestSubclass extends FinalTest {
public final String name = "FinalTestSubclass";
public FinalTestSubclass()
{
}
}
}
Read more about final variables
In reply to your comment to matt's answer; you can achieve determining the constant in the subclass by passing it in the constructor:
public class FinalTest {
public final String name;
public FinalTest()
{
this("FinalTest");
}
protected FinalTest(String nameConstant)
{
name = nameConstant;
}
public static class FinalTestSubclass extends FinalTest {
public FinalTestSubclass()
{
super("FinalTestSubclass");
}
}
}
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.