Scope Issue. How to reference method? - java

I have this scenario:
public class A
{
private final Integer index;
public Integer getIndex() { return index; }
public static class B
{
//unimportant
}
}
public class C extends B
{
//how to reference getIndex() here?
}
How can I call getIndex() in class C's body?

Odd scenario... but you'd have to move class C to also be an inner class inside class A. Shrug? Curious why are you extending an inner class in the first place? What are the restrictions of the design that are causing this? Not judging you at all. Having the thinking behind the design could aide in possibly finding an alternative solution.
public class A
{
// make sure final value is set here or in constructor
private final Integer index = 0;
public Integer getIndex() { return index; }
public static class B
{
//unimportant
}
//Doesn't make much sense... but...
public class C extends B
{
//can now call getIndex()
public void callGetIndex() {
getIndex();
}
}
}
Bonus research:
For those that are maybe as curious as me and thought about using this to reference the function from another file. If you compile C in another file, and try accessing getIndex by using the enclosing this:
A.this.getIndex();
Sadly that won't work because even though C extends B, it still needs to be enclosed by A for that methodology to work. You get this compile time error:
C.java:5: error: not an enclosing class: A
A.this.getIndex();
^
1 error
Hey cool! another answer, based off #mzl's answer below:
So interestingly enough, You can keep B static and extend both classes to get what you want to do. This is useful for example if you can not edit file A.java, because A.java is 3rd party functionality. (give #mzl credit here for his answer below)
Here is how you'd do it that way! ( Tested this compiles via javac A.java C.java )
A.java
public class A
{
private final Integer index = 0;
public Integer getIndex() { return index; }
public static class B
{
//unimportant
}
}
C.java
public class C extends A
{
public class D extends A.B {
//can now call getIndex()
public void callGetIndex() {
getIndex();
}
}
}
I've created a static over flow project proving #mzl's theory here:
https://github.com/davethomas11/stackoverflow_Q_39441077
One gothcha. You'll notice I create an instance of C before D to make sure there is access to getIndex(). I haven't tested what happens if you instantiate D directly I will do that later and post the results.
Late update on that instantiate D directly test.
I added C.D testD = new C.D(); in my static main function:
$ sh build.sh
StackOverflowQuestion39441077.java:5: error: an enclosing instance that contains C.D is required
C.D testD = new C.D();
^
1 error
The compiler helps us by not letting us do this.

If you want to extend (non-statically) a inner class you must extend the outer class aswell.
You could do it this way:
public class A
{
private final Integer index;
public Integer getIndex() { return index; }
public static class B {}
}
public class D extends A{
public class C extends B{}
}

You can't. C extends B which does not have a getIndex() method. C must extend A to inherit that method.

(I feel it is an interesting theoretical question but with little meaning in practice.)
You can't event access A.getIndex from B because B is static, and getIndex is not, so to invoke getIndex you need a non-null instance of A.
Assuming you could make B non-static, you couldn't either, because your scheme becomes contradictory:
In one hand, class B is inner, so to instantiate a new object a previous non-null instance of A is required:
A a=new A();
B b=a.new B();
But in the other hand, class C is a top-level (not inner) class, so it may be directly instantiated. However, being a subclass of B, it is subject to the same restrictions as its superclass: It needs an instance of A. Contradictory!
The only way I think to make it work is to declare getIndex static, so no instance of A would be needed (in fact, neither subclassing from B would be a problem).

Related

How to use methods from extended class on objects from main class? [JAVA]

I'm starting with developing something, and I have few classes that are using the same methods, so I want to have it in one class (to easy fixing in one place etc). Problem is that I dont know how to use methods from different classes on object in main class. Code for explanation:
public class A extends C {
public UiDevice device;
device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
public void test(){
methodFromC();
}
}
public class B extends C {
public UiDevice device;
device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
public void test(){
methodFromC();
}
}
public class C {
protected void methodFromC(){
device.something();
}
}
I know that I can do it by adding argument to methodFromC:
public class C {
protected void methodFromC(UiDevice device){
device.something();
}
and running it by
methodFromC(device);
But maybe is there better solution?
First of all, as a beginning programmer unless you are doing it for school, avoid extending classes. It ends up a big spaghetti mess until you learn to moderate it (I fell for this one big-time), What you are trying to do isn't good code right now.
I THINK what you are trying to do, however is something like this:
(Assume unspecified code remains pretty much as it is)
class A extends C
{
public UiDevice getDevice()
{
return device;
}
}
abstract class C
{
public abstract UiDevice getDevice();
public methodFromC()
{
getDevice().doSomethingToDevice();
}
}
This pattern allows you to access something from A in a parent class.
B can also have it's own device. I believe this is what you are after (C being able to operate on A's device or B's device depending on which one extended C).
Get rid of the public variable.
You can use the super keyword to access anything from the class you are extending. In your case :
public class B extends C {
public UiDevice device;
device = super.methodFromB();
public void test(){
methodFromB();
}
}
If many of your classes declare methods that do the same thing, you can make them inherit from one class, let's call it class A. In class declare and implement the method. Then in child classes declare methods and in their body write:
super.nameOfYourMethodFromParentClass();
In general, to use a method from different class you just create an object of the class and call a method on it. Like:
class A {
public void myMethod() {
B b = new B();
b.methodFromB();
}
}
When it comes to inheritance be aware of this:
You can create an object of a class that declares this method or of a class that inherits from the class that declares this method and call the method on this object.
Like:
Class A inherits from C. In class C you have method methodFromC() declared. To invoke method from class C on object from class A you can do:
A a = new A();
a.methodFromC(device);
The invoked method here is the method from class C.
But if in class A you override method from class C (that means in class A you declare a method that has the same name and parameters as method in class C), then by executing the code I have written above you will invoke the method from class A, not class C.

T and inheritance in Java

I have a class A with static field F:
class A {
public static String F = null;
}
Class B:
class B extends A {
public static String F = "somestring";
}
and a typed class with a method that uses field F:
class C<T extends A> {
public void someMethod() {
String someString = T.F;
// Manipulations with someString
}
}
And then my code that calls it.
C<B> c = new C<B>();
c.someMethod();
and I'm getting a null pointer exception when trying to manipulate with someString. So, the T.F is null, but T is B, so it should be "somestring"! Why?
You can't Override fields. Since it is extends A, it will always use the field in A.
Add a getter in class A and B that returns F. From there, Override the method in A with the one in B.
class A {
public String getF(){
return null;
}
}
class B {
#Override
public String getF(){
return "someString";
}
}
This doesn't have to do with generics.
The fields of a class cannot be overridden by a subclass - only methods can. So, even if you define a field in your subclass with the same name as the one in the superclass, you're merely creating a new field that simply happens to have the same name but actually shadows (not overrides) the previous one.
Consider putting an assignment with the default value of the field in the constructor of your subclass. Then it should work.
A static member in Java can be hidden, but not overridden. A reference to a static member is resolved at compile time - and at compile time, the only known type of T is A.
See http://www.coderanch.com/how-to/java/OverridingVsHiding.
Edit: A field cannot be overridden anyway, whether it is static or instance.
This happens because all the static members of A are common to A alone and cannot be inherited by B.
No new static member, which is not present in A, can be present in B.
Virtually, when you say
class C < T extends A > {
...
}
You can only use methods(both static and instance - unless #Overriden) and fields which are common in A. So, since F is not an instance field, it is not overriden and the JVM finds the occurance of F in A.
Hence you get an NPE.

Java design, how do I avoid passing object down the hierarchy?!? Impossible?

I have a number of classes, please allow me to introduce them and then ask my question at the end:
I have a container class which contains two objects in a composite relationship:
public class Container{
A a;
B b;
public someMethod(){
a.getC().myMethod(b);
}
}
A and B are superclasses (or Interfaces), with subtypes that can also be the type held in the composite relationship.
A contains a member of (interface) type C:
public class A{
C c;
}
public interface C{
public void myMethod(B b);
}
public class D implements C{
public void myMethod(B b){
//This code will modify the state of object b, in class Container.
b.changeState();
}
}
public class E implements C{
public void myMethod(B b){
//This code will modify the state of object b, in class Container.
b.changeState();
}
}
My problem is that I wish to modify the state of object b from a method starting in the container class, which eventually calls code down the hierarchy, to classes D and E- calling myMethod() via dynamic binding. I want to do this because I am going to use polymorphism to run the correct myMethod() (depending on whether the type of object is D or E) and I wish to do this, rather than write IF statements.
So my problem is that it seems very bad continually passing the instance of object b down the class hierarchy to myMethod, so that I can run b-specific code to modify the state of b. Is there anything else I can do to modify b from d and e (collectively known as c)?
I can get this to work using just interfaces but without using generics- but when I added generics i had problems with types and that made me start to think if my whole design was flawed?
EDIT: I could probably do this easily just by using IF statements- but I wanted an elegant solution using polymorphism of classes D and E.
First of all, if I understood your question correctly, no instance of B is being "passed down" in your code. Dynamic dispatch will simply cause the myMethod() implementation in the actual type of a to be called with an instance of B as argument.
While it may be tedious to have to write the argument explicitly every time you implement myMethod(), there's nothing wrong with it.
The alternative is to give each subclass/implementation of A an attribute of type B. In this case, however, you would have to pass your B instance down the chain of constructors to the class that actually has your B attribute.
Your code would become:
public class A{
C c;
public A(C c) {
this.c = c;
}
public interface C{
public void myMethod(B b);
}
public abstract class CC {
protected B b;
public CC(B b) {
this.b = b;
public class D extends CC implements C {
public D(B b) {
super(b);
}
public void myMethod(){
b.changeState();
}
}
public class E extends CC implements C {
public E(B b) {
super(b);
}
public void myMethod(){
b.changeState();
}
}
And then somewhere, e.g. in Container's constructor:
b = new B();
a = new A(new E(b));
You could pass the instance of B to the constructor of E. (or use a setter). That poses issues in itself, but at least it avoids having to pass B down every time you call myMethod(), which now needs no arguments.
e.g.
somewhere inside B
E myE = new E(this);
and, inside E
final B myB;
public E(B myHigherLevelThing) {
this.myB = myHigherLevelThing;
}
public void myMethod() {
myB.changeState();
}
Use the most general interface for the declarations, I'm a little confused about your full hierarchy so there may be room for improvement there...

Java Class inheritance: can I make non static member in the parent class become static in the son?

Before you start reading I would like to clarify:
I have already thought of other designs and work arounds
I'm only interested in the problem I exposed and not "changing" it (so no solutions such as delete the points in A and create new points fields in B and C...
lets consider the following code:
public class A {
protected cpVect[][] points = null;
...
}
and its classes that inherits it:
public class B extends A{
...
}
public class C extends A{
...
}
so far so good.
my problem is that for B and C contains arrays of points that will be created in the constructor using something like
if(points == null){calculate points code}
the problem is as follow
points in A can't be static because the dimensions are different in B and C.
but every instance of B will share the B points and every instance of C will share the C points. (in other words a Square will always be a square and a triangle will always be a triangle). and therefore I want to have the B:points and C:points static so that i don't get duplicates of the values for every instance.
So is there a way to redefine points as static in B and C when it is not static in A?
If you access points solely through property methods (getters/setters) you can do whatever you want in the subclasses. If you use inheritance, A will have to be an abstract class. Otherwise you'd always carry around the empty points variable in A (losing 8 bytes, probably).
In this case the hierarchy would look like this:
abstract class A {
abstract public cpVect[][] getPoints();
// more methods ...
}
public class B extends A {
private final static cpVect[][] POINTS = calculatePoints();
#Override
public cpVect[][] getPoints() {
return POINTS;
}
private cpVect[][] calculatePoints() {
// ...
}
}
And the same for C. If A includes no other state or functionality, you should make it an interface.
You can't make the field static, but you could make it a singleton. You'll have multiple references to the singleton, but you'll only need one copy of each points array. For example, in B:
class B extends A {
private cpVect[][] B_points = null;
public B() {
if (B_points == null)
B_points = create_B_points();
points = B_points;
}
}
If multithreaded, you'll need to add synchronization.
(Sorry for earlier half-finished version. The SO editor seems quirky in Chrome).
There is no significance of static and non-static in inheritance. ie if you have a member variable in a parent class then you can have the same name for the static member of the child class. as shown
class test {
public int a;
}
class test1 extends test {
public static int a;
}
And through objects you can access a of test.
through class test1 you can access static a of test1. as both are independent.
You cannot have a same variable as the member in parent and static in child.

Java; casting base class to derived class

Why can't I cast a base class instance to a derived class?
For example, if I have a class B which extends a class C, why can't I do this?
B b=(B)(new C());
or this?
C c=new C();
B b=(B)c;
Alright let me be more specific as to what I'm trying to do. Here's what I have:
public class Base(){
protected BaseNode n;
public void foo(BaseNode x){
n.foo(x);
}
}
public class BaseNode(){
public void foo(BaseNode x){...}
}
Now I want to create a new set of classes which extend Base and Basenode, like this:
public class Derived extends Base(){
public void bar(DerivedNode x){
n.bar(x);//problem is here - n doesn't have bar
}
}
public class DerivedNode extends BaseNode(){
public void bar(BaseNode){
...
}
}
So essentially I want to add new functionality to Base and BaseNode by extending them both, and adding a function to both of them. Furthermore, Base and BaseNode should be able to be used on their own.
I'd really like to do this without generics if possible.
Alright so I ended up figuring it out, partly thanks to Maruice Perry's answer.
In my constructor for Base, n is instantiated as a BaseNode. All I had to do was re-instantiate n as a DerivedNode in my derived class in the constructor, and it works perfectly.
because if B extends C, it means B is a C and not C is a B.
rethink what you are trying to do.
The existing answers are fine in terms of an abstract argument, but I'd like to make a more concrete one. Suppose you could do that. Then this code would have to compile and run:
// Hypothetical code
Object object = new Object();
InputStream stream = (InputStream) object; // No exception allowed?
int firstByte = stream.read();
Where exactly would the implementation of the read method come from? It's abstract in InputStream. Where would it get the data from? It simply isn't appropriate to treat a bare java.lang.Object as an InputStream. It's much better for the cast to throw an exception.
In my experience it's tricky to get "parallel class hierarchies" like the one you're describing to work. You may find that generics help, but it can get hairy very quickly.
You need to use the instanceof keyword to check the type of object referenced by n and typecast the object and call the bar() method. Checkout Derived.bar() method bellow
public class Test{
public static void main(String[] args){
DerivedNode dn = new DerivedNode();
Derived d = new Derived(dn);
d.bar( dn );
}
}
class Base{
protected BaseNode n;
public Base(BaseNode _n){
this.n = _n;
}
public void foo(BaseNode x){
n.foo(x);
}
}
class BaseNode{
public void foo(BaseNode x){
System.out.println( "BaseNode foo" );
}
}
class Derived extends Base{
public Derived(BaseNode n){
super(n);
}
public void bar(DerivedNode x){
if( n instanceof DerivedNode ){
// Type cast to DerivedNode to access bar
((DerivedNode)n).bar(x);
}
else {
// Throw exception or what ever
throw new RuntimeException("Invalid Object Type");
}
}
}
class DerivedNode extends BaseNode{
public void bar(BaseNode b){
System.out.println( "DerivedNode bar" );
}
}
You can create a constructor for B that takes C as a parameter.
See this post for ideas to do what you're trying to do.
Base classes shouldn't know anything about classes derived from them, otherwise the problems highlighted above will arise. Downcasting is a 'code smell', and downcasting in the base class to a derived class is particularly 'smelly'. Such designs can lead to difficult to resolve circular dependencies too.
If you want a base class to make use of derived class implementations use the Template method pattern i.e add a virtual or abstract method in your base class and override and implement it in the derived class. You can then safely call this from the base class.
You can't do that because C does not necessarily implement the behaviours you created when you extended it in B.
So, say C has a method foo(). Then you know that you can call foo() on a B, as B extends C, so you can cast accordingly a treat a B as if it was a C with (C)(new B()).
However - if B has a method bar(), nothing in the subclass relationship says that you can call bar() on C too. Thus you cannot treat a C as if it were a B, and so you cannot cast.
In your exemple, you can cast n into a DerivedNode if you are certain that n is an instance of DerivedNode, or you can use generics:
public class Base<N extends BaseNode> {
protected N n;
public void foo(BaseNode x){
n.foo(x);
}
}
public class BaseNode {
public void foo(BaseNode x){...}
}
public class Derived extends Base<DerivedNode> {
public void bar(DerivedNode x){
n.bar(x); // no problem here - n DOES have bar
}
}
public class DerivedNode extends BaseNode {
public void bar(BaseNode){
...
}
}
Because if B extends C, then B might have stuff that isn't in C (like instance variables you initialize in the constructor that are not in new C())

Categories

Resources