How to set fields in an abstract class? - java

I have an abstract class with a field in it, which should have following properties:
readonly for the public interface
writeonly for the subclasses
My question now is: how should I set and initialize this field?
public abstract class A {
// initialize it here ?
private int field = 0;
// initialize it in constructor ?
protected A(int field)
{
this.field = field;
}
// use protected setter ?
protected void setField(int val){
this.field = val;
}
// or use protected field
protected int field;
public int getField(){
return field;
}
}
How to initialize/access this field?
public class B extends A {
public B(int val){
super(val);
// or
setField(val);
// or
field = val;
}
}
and is it a good idea to use something like a protected constructor?

It's basically on your need
If you want to initialize super class field at the creation of child object it self, then you could call super(val);
If you want to create your child object independent of parent object's field values. use Default contructor for child class and if required to set parent value call setField(val); method on child object.
is it a good idea to use smth. like a protected constructor ?
Yes if you really want to restrict access for the classes within the package

Related

Setting value to abstract private field from subclass

I would like to know about the most efficient way to set a value to an abstract private field from a subclass. So, for example, have a field called itemCost, then I would like to initialize its value to 200 in the subclass.
There is no such abstract private field in Java. Only classes and methods can be abstract. But to emulate an abstract field, I believe there are at least two good methods:
Method (1): Define an uninitialized final field in the superclass. And initialize it in the child class. This is more suitable to constant (primitive) variables and having the variable initialized in the constructor is perfectly fine. It will also work well with complex types of course (class instances with mutable content, instead of primitive types).
Method (2): Define an abstract setter for the field to force the subclass to implement/redefine this method and do the specific initializations. This is more suitable for varying field content but there is no guarantee that the field will be correctly initialized by all subclasses. This becomes implementation-dependent.
Method (1)
abstract class MySuperClass {
final int itemCost;
protected MySuperClass(int _itemCost) {
this.itemCost = _itemCost;
}
}
class MySubClass extends MySuperClass {
public MySubClass() {
super(200);
}
public MySubClass(int itemCost) {
super(itemCost);
}
}
If you do not call super(itemCost) you will get a compiler error. So this is very enforcing.
Method (2)
abstract class MySuperClass {
int itemCost;
protected MySuperClass() { }
abstract void setItemCost();
abstract void setItemCost(int _itemCost);
}
class MySubClass extends MySuperClass {
public MySubClass() {
setItemCost();
}
public MySubClass(int itemCost) {
setItemCost(itemCost);
}
#Override
final void setItemCost() {
this.itemCost = 200;
}
#Override
final void setItemCost(int _itemCost) {
this.itemCost = _itemCost;
}
}
If you are interested in modifying the value after instantiation and if the child class is correctly implemented, then it is a fine solution. But it is a more verbose, less intuitive and error-prone solution.

How to access protected field of a super class in java from subclasses?

I want to access a protected field of a super-class from a sub-class in Java:
Class Super {
protected int field; // field set to a value when calling constructor
}
Class B extends Super { // field of super class is set to value when calling
// constructor
}
Class C extends Super { // same here
}
B b = new B();
C c = new C();
b.super.field ?
The class can access the field directly, as if it were its own field. The catch is that the code doing the access must be in the code of the derived class itself, not in the code using the derived class:
class B extends Super {
...
int getSuperField() {
return field;
}
}
The protected modifier allows a subclass to access the superclass members directly.
But the access should be made inside the subclass or from the same package.
Example:
package A;
public class Superclass{
protected String name;
protected int age;
}
package B;
import A.*;
public class LowerClass extends SuperClass{
public static void main(String args[]){
LowerClass lc = new LowerClass();
System.out.println("Name is: " + lc.name);
System.out.println("Age is: " + lc.age);
}
}
From Javadoc:
The protected modifier specifies that the member can only be accessed within its own package (as with package-private) and, in addition, by a subclass of its class in another package.
In either Super or B, create a getter method:
public int getField() {
return field;
}
Then you can do:
B b = new B();
int field = b.getField();
It's not allowed to access a protected field outside the body of the declaring and extending class.
See here 6.6.2 Access to a protected Member
A protected member or constructor of an object may be accessed from outside the package in which it is declared only by code that is responsible for the implementation of that object.
The solution would be any of the answers with a setter/getter or making it public.

Accessing a parent class's protected method from outside a child class (with reflection or anything that would work)

I've looked around for a solution with no luck, here's what I have and what I'm trying to achieve
Parent Class
public abstract class MyAbstractParentClass{
private String privateParentField;
protected String getPrivateParentField(){
return privateParentField;
}
public void setField(String value){
privateParentField = value;
}
}
Child Class
public class MyChlidClass extends MyAbstractParentClass{
#Override
public void setField(String value){
super.setField(value);
}
}
I'm trying to call the MyChlidClass 's setField method and then call the MyAbstractParentClass 's protected String getPrivateParentField() afterwords;
#Test
public void f(){
Method[] m = MyChlidClass.class.getDeclaredMethods();
for (Method method : m) {
System.out.println(method.getName());
}
}
But this code above returns only declared methods in MyChlidClass without the parent class's protected ones, how could I access the protected method? any ideas?
thank you very much in advance :)
EDIT
Here's the final solution for those interested
MyChildClass child = new MyChildClass();
chlid.setField("FOO_BAR");
Method getPrivateParentField = child.getClass().getSuperclass().getDeclaredMethod("getPrivateParentField");
getPrivateParentField.setAccessible(true);
String result = (String) getPrivateParentField.invoke(child);
System.out.println((String)result); //prints out FOO_BAR
PS : there are some exceptions you can either catch or add throws declaration for them;
thanks again for your help
You can get the super class methods by calling
MyChlidClass.class.getSuperclass().getDeclaredMethods();
You cannot access protected methods directly from outside class. It can only be accessed from within the class or inherited classes. To access this from outside, you will have to create a public method in the child class that calls the protected method of the parent.
You can increase the visibility when you extend a class. You don't need to change the code of MyChlidClass, you can just extend it:
public class MyGrandChlidClass extends MyChlidClass{
#Override
public String getPrivateParentField(){
return super.getPrivateParentField();
}
}
#Test
public void f(){
MyGrandChlidClass myGrandChlidClass = new MyGrandChlidClass();
myGrandChlidClass.setField("hello");
System.out.println(myGrandChlidClass.getPrivateParentField());
}
Use getDeclaredMethods() on the parent class to get information about the parent classes' protected methods.

How to access the private variables of a class in its subclass?

This is a question I was asked in an interview: I have class A with private members and Class B extends A. I know private members of a class cannot be accessed, but the question is: I need to access private members of class A from class B, rather than create variables with the same value in class B.
The interviewer was either testing your knowledge of access modifiers, or your approach to changing existing classes, or both.
I would have listed them (public, private, protected, package private) with an explanation of each. Then gone on to say that class A would need to be modified to allow access to those members from class B, either by adding setters and getters, or by changing the access modifiers of the members. Or class B could use reflection. Finally, talk about the pros and cons of each approach.
Reflection? Omitting imports, this should work:
public class A {
private int ii = 23;
}
public class B extends A {
private void readPrivateSuperClassField() throws Exception {
Class<?> clazz = getClass().getSuperclass();
Field field = clazz.getDeclaredField("ii");
field.setAccessible(true);
System.out.println(field.getInt(this));
}
public static void main(String[] args) throws Exception {
new B().readPrivateSuperClassField();
}
}
It'll not work if you do something like that before the of invocation readPrivateSuperClassField();:
System.setSecurityManager(new SecurityManager() {
#Override
public void checkMemberAccess(Class<?> clazz, int which) {
if (clazz.equals(A.class)) {
throw new SecurityException();
} else {
super.checkMemberAccess(clazz, which);
}
}
});
And there are other conditions under which the Reflection approach won't work. See the API docs for SecurityManager and AccessibleObject for more info. Thanks to CPerkins for pointing that out.
I hope they were just testing your knowledge, not looking for a real application of this stuff ;-) Although I think an ugly hack like this above can be legit in certain edge cases.
The architecture is broken. Private members are private because you do not want them accessed outside the class and friends.
You can use friend hacks, accessors, promote the member, or #define private public (heh). But these are all short term solutions - you will probably have to revisit the broken architecture at some stage.
By using public accessors (getters & setters) of A's privates members ...
You cannot access private members from the parent class. You have make it protected or have protected/public method that has access to them.
EDIT : It is true you can use reflection. But that is not usual and not good idea to break encapsulation.
A nested class can access to all the private members of its enclosing class—both fields and methods. Therefore, a public or protected nested class inherited by a subclass has indirect access to all of the private members of the superclass.
public class SuperClass
{
private int a = 10;
public void makeInner()
{
SubClass in = new SubClass();
in.inner();
}
class SubClass
{
public void inner()
{
System.out.println("Super a is " + a);
}
}
public static void main(String[] args)
{
SuperClass.SubClass s = new SuperClass().new SubClass();
s.inner();
}
}
If I'm understanding the question correctly, you could change private to protected. Protected variables are accessible to subclasses but behave like private variables otherwise.
By using setters and getters u can access it
From JLS §8.3. Field Declarations:
A private field of a superclass might be accessible to a subclass - for example, if both classes are members of the same class. Nevertheless, a private field is never inherited by a subclass.
I write the example code:
public class Outer
{
class InnerA
{
private String text;
}
class InnerB extends InnerA
{
public void setText(String text)
{
InnerA innerA = this;
innerA.text = text;
}
public String getText()
{
return ((InnerA) this).text;
}
}
public static void main(String[] args)
{
final InnerB innerB = new Outer().new InnerB();
innerB.setText("hello world");
System.out.println(innerB.getText());
}
}
The explanation of the accessibility of InnerA.text is here JLS §6.6.1. Determining Accessibility:
Otherwise, the member or constructor is declared private, and 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.
You can use the setters and getters of class A. Which gives same feeling as if You are using a class A's object.
Have you thought about making them protected ? Just to be sure you are aware of this option, if you are then pardon me for bringing up this trivia ;)
Private members cant be accessed in derived class
If you want to access means you can use getter and setter methods.
class A
{
private int a;
void setA(int a)
{
this.a=a;
}
int getA()
{
return a;
}
}
Class B extends A
{
public static void main(String[] arg)
{
B obj= new B();
obj.setA(10);
System.out.println("The value of A is:"+obj.getA());
}
}
Private will be hidden until you have been given the right access to it. For instance Getters or setters by the programmer who wrote the Parent. If they are not visible by that either then accept the fact that they are just private and not accessible to you. Why exactly you want to do that??
I don't know about Java, but in some languages nested types can do this:
class A {
private string someField;
class B : A {
void Foo() {
someField = "abc";
}
}
}
Otherwise, use an accessor method or a protected field (although they are often abused).
A private member is accessible in subclass in a way that you cannot change the variable, but you are able to access the variable as read only.
Obviously, making them protected, or adding setters/getters is the preferred technique. Reflection is a desperation option.
Just to show off to the interviewer, IF "access" means read access, and IF Class A generates XML or JSON etc., you could serialize A and parse the interesting fields.
Class A
{
private int i;
int getValue()
{
return i;
}
}
class B extends A
{
void getvalue2()
{
A a1= new A();
sop(a1.getValue());
}
}
To access private variables of parent class in subclass you can use protected or add getters and setters to private variables in parent class..
You can't access directly any private variables of a class from outside directly.
You can access private member's using getter and setter.
Ways to access the superclass private members in subclass :
If you want package access just change the private fields to protected. It allows access to same package subclass.
If you have private fields then just provide some Accessor Methods(getters) and you can access them in your subclass.
You can also use inner class e.g
public class PrivateInnerClassAccess {
private int value=20;
class InnerClass {
public void accessPrivateFields() {
System.out.println("Value of private field : " + value);
}
}
public static void main(String arr[])
{
PrivateInnerClassAccess access = new PrivateInnerClassAccess();
PrivateInnerClassAccess.InnerClass innerClass = access.new InnerClass();
innerClass.accessPrivateFields();
}
}
4 .You can also use Reflection e.g
public class A {
private int value;
public A(int value)
{
this.value = value;
}
}
public class B {
public void accessPrivateA()throws Exception
{
A a = new A(10);
Field privateFields = A.class.getDeclaredField("value");
privateFields.setAccessible(true);
Integer value = (Integer)privateFields.get(a);
System.out.println("Value of private field is :"+value);
}
public static void main(String arr[]) throws Exception
{
B b = new B();
b.accessPrivateA();
}
}
You can use Accessors (getter and setter method) in your Code.
By using setter method you can use else with the help of refection you can use private member of class by setting that member say a -
take a from class
and set a.setAccessible(true);
You may want to change it to protected.
Kindly refer this
https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html
If this is something you have to do at any cost just for the heck of doing it you can use reflection. It will give you list of all the variables defined in the class- be it public, private or protected. This surely has its overhead but yes, it is something which will let you use private variables. With this, you can use it in any of the class. It does not have to be only a subclass
Please refer to the example below. This may have some compilation issues but you can get the basic idea and it works
private void getPropertiesFromPrivateClass(){
Field[] privateVariablesArray = PrivateClassName.getClass().getDeclaredFields();
Set<String> propertySet = new HashSet<String>();
Object propertyValue;
if(privateVariablesArray.length >0){
for(Field propertyVariable :privateVariablesArray){
try {
if (propertyVariable.getType() == String.class){
propertyVariable.setAccessible(true);
propertyValue = propertyVariable.get(envtHelper);
System.out.println("propertyValue");
}
} catch (IllegalArgumentException illegalArgumentException) {
illegalArgumentException.printStackTrace();
} catch (IllegalAccessException illegalAccessException) {
illegalAccessException.printStackTrace();
}
}
Hope this be of some help.
Happy Learning :)
Below is the example for accessing the private members of superclass in the object of subclass.
I am using constructors to do the same.
Below is the superclass Fruit
public class Fruit {
private String type;
public Fruit() {
}
public Fruit(String type) {
super();
this.type = type;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
Below is subclass Guava which is inheriting from Fruit
public class Guava extends Fruit{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Guava(String name,String type) {
super(type);
this.name=name;
}
}
Below is the main function where we are creating an object of subclass and also displaying the member of superclass.
public class Main {
public static void main(String[] args) {
Guava G1=new Guava("kanpuria", "red");
System.out.println(G1.getName()+" "+G1.getType());
}
}
Note that a private field of a superclass might be accessible to a subclass (for example,if both classes are memebers of the same class),Nevertheless,a private field is never inherited
by a subclass
Simple!!!
public class A{
private String a;
private String b;
//getter and setter are here
}
public class B extends A{
public B(String a, String b){ //constructor
super(a,b)//from here you got access with private variable of class A
}
}
thanks
Directly we can't access it. but Using Setter and Getter we can access,
Code is :
class AccessPrivate1 {
private int a=10; //private integer
private int b=15;
int getValueofA()
{
return this.a;
}
int getValueofB()
{
return this.b;
}
}
public class AccessPrivate{
public static void main(String args[])
{
AccessPrivate1 obj=new AccessPrivate1();
System.out.println(obj.getValueofA()); //getting the value of private integer of class AccessPrivate1
System.out.println(obj.getValueofB()); //getting the value of private integer of class AccessPrivate1
}
}
Modifiers are keywords that you add to those definitions to change their meanings. The Java language has a wide variety of modifiers, including the following:
Java Access Modifiers
Non Access Modifiers
To use a modifier, you include its keyword in the definition of a class, method, or variable. The modifier precedes the rest of the statement.
There is more information here:
http://tutorialcorejava.blogspot.in/p/java-modifier-types.html

In Java, why can't I declare a final member (w/o initializing it) in the parent class and set its value in the subclass? How can I work around?

In a Java program, I have multiple subclasses inheriting from a parent (which is abstract). I wanted to express that every child should have a member that is set once only (which I was planning to do from the constructor). My plan was to code s.th. like this:
public abstract class Parent {
protected final String birthmark;
}
public class Child extends Parent {
public Child(String s) {
this.birthmark = s;
}
}
However, this seems to not please the Java gods. In the parent class, I get the message that birthmark "might not have been initialized", in the child class I get "The final field birthmark cannot be accessed".
So what's the Java way for this? What am I missing?
You can't do it because while comparing the parent class, the compiler can't be sure that the subclass will initialize it. You'll have to initialize it in the parent's constructor, and have the child call the parent's constructor:
public abstract class Parent {
protected final String birthmark;
protected Parent(String s) {
birthmark = s;
}
}
public class Child extends Parent {
public Child(String s) {
super(s);
...
}
}
Pass it to the parent constructor:
public abstract class Parent {
private final String birthmark;
public Parent(String s) {
birthmark = s;
}
}
public class Child extends Parent {
public Child(String s) {
super(s);
}
}
Another Java-ish way to do this is probably to have the parent class to define an abstract "getter", and have the children implement it. It's not a great way to do it in this case, but it in some cases it can be exactly what you want.
I would do it like this:
public abstract class Parent
{
protected final String birthmark;
protected Parent(final String mark)
{
// only if this makes sense.
if(mark == null)
{
throw new IllegalArgumentException("mark cannot be null");
}
birthmark = mark;
}
}
public class Child
extends Parent
{
public Child(final String s)
{
super(s);
}
}
final means that the variable can be initialized once per instance. The compiler isn't able to make sure that every subclass will provide the assignment to birthmark so it forces the assignment to happen in the constructor of the parent class.
I added the checking for null just to show that you also get the benefit of being able to check the arguments in one place rather than each cosntructor.
Why not delegate initialization to a method. Then override the method in the parent class.
public class Parent {
public final Object x = getValueOfX();
public Object getValueOfX() {
return y;
}
}
public class Child {
#Override
public Object getValueOfX() {
// whatever ...
}
}
This should allow custom initialization.
Yes, the final members are to be assigned in the class in which they are declared. You need to add a constructor with a String argument to Parent.
Declare a constructor in the superclass that's called by the subclass.
You must set the field in the superclass to make sure it's initialized, or the compiler can't be sure the field is initialized.
You probably want to have a Parent(String birthmark) constructor so that you can ensure in your Parent class that final is always initialized. Then you can call super(birthmark) from your Child() constructor.

Categories

Resources