How to access (shadowing) member variables in subclass from method in superclass? - java

Let me know if someone does not understand the question. I tried my best to frame the question below.
I have a common method in parent class for generating pattern. For re usability, I thought to retain this method under parent class.
Inside the method, I use several variables. So I thought it is better to pass the object as the parameter to the method generatePattern. But since variables cannot be overridden, how can I use respective variables from these sub classes? Any other feature in java other than using subclass? Will "Generic types" as parameter work in such case?
class Parent {
int var1;
String[] values;
void generatePattern(Parent obj1) {
// This will not make use of respective values of
// subclass object that is passed I guess.
newPattern(obj1.values, obj1.var1);
}
}
class AscendSubClass extends Parent {
int var1 = 5;
String[] values = {"S", "R"};
}
class DescendSubClass extends Parent {
int var1 = 10;
String[] values = {"N", "D"};
}
I may pass either AscendSubClass or DescendSubClass above to generatePattern().
Inside this method, I need to use the variables var1, values and many other variables of subclasses.
These variables are of same type and have same name, but the values are different and depends on the subclass. How can I refer these variables now in generatePattern() so that method does not change?
It is possible to achieve this by making variables as a parameters to methods or by if/else statements, but I have several variables to pass and it is big inconvenience.

Add a getter method and override it in either subclass.
public int getVar() {
return var1;
}

Related

Java super class variable accessed outside of subclass?

If I have three classes as follows:
package com.Bob.Marley;
public class SuperClass{
protected int x = 0;
}
package com.Bob.Marley;
public class SubClass extends SuperClass{
protected int x = 1;
}
package com.Bob.Marley;
public class TestClass{
public static void main (String[] args){
SubClass s = new SubClass();
//print 1
System.out.println(s.x);
//how do I print the superclass variable?
//I know inside SubClass I can access it with plain old super.x
//but what about outside the subclass with a new object.
}
}
So the question is how would I print out 0 from the superclass of the new object s created in a separate class. System.out.println(s.super.x); does not work. I don't think it changes anything but I am using java 8.
The expression s.super.x is invalid here. Whenever you prefix a super.x with something, it should be a type name, not a variable name, e.g. SuperClass.super.x. However, this would be valid only inside the subclass for accessing the superclass of the enclosing class, which does not exist here.
Cast x to be a SuperClass so you can access the x declared in Superclass.
System.out.println( ((SuperClass) s).x);
or
SuperClass sc = (SuperClass) s;
System.out.println(sc.x);
This works because variable access is statically binded. The type of the variable or expression determines the scope searched for variable access.
TL;DR: if you introduce a new field in a subclass, don't re-use a field name from the parent class. You gain nothing, only confusion and problems.
If I understand correctly, you want SubClass instances to have two fields, one inherited from the SuperClass (for the discussion, let's rename that to superX to make things clearer), and one from the subclass itself (let's rename that to subX).
For a given SubClass instance, you want to be able to access both fields, superX and subX (of course, using different expressions). What makes things difficult in your code sample, is the fact that you chose to give both of them the same name x.
So, if you really want your instances to carry both fields, I'd recommend to rename them, so you don't have to use ugly tricks like casting to the SuperClass.
public class SuperClass{
protected int superX = 0;
}
public class SubClass extends SuperClass{
protected int subX = 1;
}
But, if x stands for the same property with the same meaning for both the super and the sub class, just with different initial values, then it doesn't make sense to have two different fields, and you should change the code to become:
public class SuperClass{
protected int x = 0;
}
public class SubClass extends SuperClass{
// constructor initializes the x field with 1.
public SubClass(){
x = 1;
}
}
Of course, then it's impossible to get two different values from a single instance of SubClass.

Constructors with "too many" parameters [duplicate]

This question already has answers here:
Managing constructors with many parameters in Java
(8 answers)
Closed 6 years ago.
Assume that I have some subclasses that extend a superclass. These subclasses differ by the parameters passed to the superclass. Unfortunately, like the following example, I can end up with "many" parameters. Is there a general method of avoiding this? Are constructors with "many" arguments considered good practice? Would it be better to have getter/setter methods instead of passing every parameter via constructor?
public abstract class SuperClass {
private int a;
private int b;
.
.
private int z;
public SuperClass(int a, int b, ... int z) {
this.a = a;
this.b = b;
.
.
this.z = z;
}
}
public class SubClass1 extends SuperClass {
public SubClass1() {
super(4, 3, ..., 9);
}
}
public class SubClass2 extends SuperClass {
public SubClass2() {
super(1, 7, ..., 2);
}
}
If your subclasses vary only in the parameters passed to the superclass, you might be looking for the Builder Pattern. A builder for the superclass lets you pass in whatever parameters you need without cluttering your constructor, and if you want subclasses for readability, you can just wrap a call to the builder and return its result from the subclass constructors.
Generally, constructors with many parameters is a code smell. It means you probably have a class that breaks the "Single Responsibility Principle". If you can't avoid it, try using the builder pattern!
I would not have constructors in my classes as the behavior of the objects instantiated by each constructor may be different and hard to determine.
One thing to check is: should SuperClass be split into simpler classes?
If this can't be done: if you have too many parameters then you can have a special class that holds the parameters; with setters and getters for each parameter.
One can fill the values in from property files, so you can have profiles for common cases.
class SuperClassParam
{
void seta(int a);
int geta();
//...
}
class SuperClass
{
public SuperClass( SuperClassParam params )
{
}
If the number of parameters can vary, then use a variable arity ("varargs") parameter. Declare an array instead of all those other instance variables. The variable arity parameter is typed as an array when in the method.
private int[] all;
public SuperClass(int... all) {
this.all = all;
}
Your subclass constructors will not have to change at all.

how to declare a helper method in java, to be used locally being able to reference variables

I have a class with several methods. Now I would like to define a helper method that should be only visible to method A, like good old "sub-functions" .
public class MyClass {
public methodA() {
int visibleVariable=10;
int result;
//here somehow declare the helperMethod which can access the visibleVariable and just
//adds the passed in parameter
result = helperMethod(1);
result = helperMethod(2);
}
}
The helperMethod is only used by MethodA and should access MethodA's declared variables - avoiding passing in explicitly many parameters which are already declared within methodA.
Is that possible?
EDIT:
The helper mehod is just used to avoid repeating some 20 lines of code which differ in only 1 place. And this 1 place could easily be parameterized while all the other variables in methodA remain unchanged in these 2 cases
Well you could declare a local class and put the method in there:
public class Test {
public static void main(String[] args) {
final int x = 10;
class Local {
int addToX(int value) {
return x + value;
}
}
Local local = new Local();
int result1 = local.addToX(1);
int result2 = local.addToX(2);
System.out.println(result1);
System.out.println(result2);
}
}
But that would be a very unusual code. Usually this suggests that you need to take a step back and look at your design again. Do you actually have a different type that you should be creating?
(If another type (or interface) already provided the right signature, you could use an anonymous inner class instead. That wouldn't be much better...)
Given the variables you declare at the top of your method can be marked as final (meaning they don't change after being initialized) You can define your helper method inside a helper class like below. All the variables at the top could be passed via the constructor.
public class HelperClass() {
private final int value1;
private final int value2;
public HelperClass(int value1, int value2) {
this.value1 = value1;
this.value2 = value2;
}
public int helperMethod(int valuex) {
int result = -1;
// do calculation
return result;
}
}
you can create an instance of HelperClass and use it inside the method
It is not possible. It is also not good design. Violating the rules of variable scope is a sure-fire way to make your code buggy, unreadable and unreliable. If you really have so many related variables, consider putting them into their own class and giving a method to that class.
If what you mean is more akin to a lambda expression, then no, this is not possible in Java at this time (but hopefully in Java 8).
No, it is not possible.
I would advise you create a private method in your class that does the work. As you are author of the code, you are in control of which other methods access the private method. Moreover, private methods will not be accessible from the outside.
In my experience, methods should not declare a load of variables. If they do, there is a good chance that your design is flawed. Think about constants and if you couldn't declare some of those as private final variables in your class. Alternatively, thinking OO, you could be missing an object to carry those variables and offer you some functionality related to the processing of those variables.
methodA() is not a method, it's missing a return type.
You can't access variables declared in a method from another method directly.
You either has to pass them as arguments or declare methodA in its own class together with the helpermethods.
This is probably the best way to do it:
public class MyClass {
public void methodA() {
int visibleVariable=10;
int result;
result = helperMethod(1, visibleVariable);
result = helperMethod(2, visibleVariable);
}
public int helperMethod(int index, int visibleVariable) {
// do something with visibleVariable
return 0;
}
}

How to store many instances of several object classes in a List

I have several Java Objects using the following classes (all part of the same super class).
Object Class one:
Class one extends Superobject {
int no;
int i;
String s;
}
Object Class two:
Class two extends Superobject {
int no;
int i;
String s;
}
I want to create many of these Objects by reading a text file and calling the constructor for Object one and Object two after every word.
I have tried storing all the Objects in a list in the super class, but somehow, I can't get the list to be non-static.
Class Superobject {
int no;
int i;
String s;
List<Superobject> li; // of course, when called with the
//method below: static List<Superobject> li
}
When I try to add Objects to the list, eclipse yells that li has to be made static.
public static void somemethod(Object one[] ones) {
for (one o : ones) {
li.add(o);
}
}
Is there a way to make it non-static or is there a better way to store the Objects?
It seems you're trying to access your non-static member l from the static method somemethod. You need to either change somemethod to be non-static as well or make l static.
Non static methods are associated with instances of the class, while static methods are associated with class itself. You are trying to access a non static member from static method.
So, the compiler cannot associate the non-static member with any object.
What you can do is either make both of them static, which you should as you trying to save several instances of Superobject in the list. If you dont make it static, every instance of Superobject will have its own list.
OR you can create a separate class and call it SuperobjectCollection and provide methods such as Add, Remove, Get etc to access the underlying List.
Consider the following pseudocode
class SuperobjectCollection {
private List<Superobject> list;
public AddObj(Superobject obj) {
list.add(obj);
}
}
You can add any logic as you see during adding, retrieving, or removing objects.
If you want to keep the list in Superobject class, you have to make it static and access it using static method. If you don't do that (like the code that you have presented), you would have following situation:
Class Superobject {
int no;
int i;
String s;
List<Superobject> li;
}
If you create two instances like:
Superobject a = new one();
Superobject b = new two();
Both a and b would contain separate li. If your somemethod is non-static you can then access this list in that method like
li.add();
or like
this.li.add();
Here this is either object a if you called the method like a.somemethod() or b if you called it like b.somemethod()
Static methods are associate with class not instance, and as such you access it like so:
Superobject.someobject();
not like
a.someobject();
It would be a terrible design decision, but assuming you can change the signature of the static method, this would help.
public static void somemethod(Object one[] ones, List<Superobject> li) {
for (one o : ones) {
li.add(o);
}
}
However, if you could change the signature of this method, you'd probably want to make it non-static anyway.
On the other hand, if all you want to achieve is to add the elements to the list. Why doesn't the following work for you?
li.addAll(Arrays.asList(ones));

Final keyword in method signatures [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Final arguments in interface methods - what’s the point?
While trying to experiment a few things, I've ran into a problem that it's described in this page.
interface B {
public int something(final int a);
}
abstract class C {
public int other(final int b);
}
class A extends C implements B {
public int something(int a) {
return a++;
}
public int other(int b) {
return b++
}
}
Why is such feature possible? I don't know why it's possible to to make a final parameter into a non-final one by just overriding the method. Why is the final keyword ignored in a method signature? And how do I obligate sub-classes to use in their methods final variables?
Java passes arguments to a method by value.
Therefore, no changes to a parameter can propagate back to the caller. It follows that whether or not the parameter is declared final makes absolutely no difference to the caller. As such, it is part of the implementation of the method rather than part of its interface.
What's your motivation for wanting to "obligate sub-classes to use in their methods final variables"?
final for a parameter only means that the value must not be changed within the method body. This is not a part of the method signature, and is not relevant to subclasses.
It should be invalid to have final parameters in interface or abstract methods, because it's meaningless.
Final variables are the only ones that can be used in closures. So if you want to do something like this:
void myMethod(int val) {
MyClass cls = new MyClass() {
#override
void doAction() {
callMethod(val); // use the val argument in the anonymous class - closure!
}
};
useClass(cls);
}
This won't compile, as the compiler requires val to be final. So changing the method signature to
void myMethod(final int val)
will solve the problem. Local final variable will do just as well:
void myMethod(int val) {
final int val0;
// now use val0 in the anonymous class
Java's final is not C++ const; there is no such thing as const-correctness in Java.
In Java, one achieves const-ness using immutable classes. It turns out to be quite effective because unlike C++, one cannot simply mess with memory. (You can use Field.setAccessible(true), and then use Reflection. But even that corruption-vector can be prevented by running the JVM with an appropriately configured security manager.)
The final keyword for arguments is not part of the method signature, and is only important for the body of the method, because Java passes all arguments by value (a copy of the value is always made for the method call).
I only use the final keyword (for arguments) if the compiler forces me to make it final, because the argument is used inside an anonymous class defined in the method.
In Java parameters are passed by value. Whether a parameter is final or not only affects that method, not the caller. I don't see why a class needs to obligate the subtypes.
Note that final parameters have one main purpose: you can't assign new values to them.
Also note that parameters are always passed by value, thus the caller won't see any assignments to the parameter inside the method.
If you really want to force parameters to be final (in order to prevent bugs that might be introduced when reassigning a parameter accidentially), employ a code anaylzer such as checkstyle.

Categories