1

I have a abstract Parent class that has multiple children. I'd like the child to be able to have a variable that is the same for every instance of that child. I'd prefer not to pass a constructor to the child to tell it it's name because that just seems silly when it can be hardcoded. From what I've read doing the following "hides" the parents instance variable and doesn't work as I want.

public abstract class Parent {
    public String name = "the parent";
    public getName(name);
}
public class Child1 extends Parent {
    public String name = "Jon";
}
public class Child2 extends Parent {
    public String name = "Mary";
}

Child1 c = new Child1();
c.getName(); // want this to return "Jon", but instead returns "the parent".

To be clear, basically what I want is something like c.getClass().getName() but I don't want to have the result of that dependent on the Class name, but rather on a hardcoded value.

Thanks

3
  • 1
    It's not very clear to me exactly what is being requested. Can you clarify the reasons you want the getName() to return what you want? Can you write a series of assertions that should (but perhaps do not) pass? Commented Apr 25, 2011 at 18:55
  • What problem are you trying to solve? Can you give a better example of why you need a class-level label (the same for every instance)? Maybe we can suggest a better alternative. Commented Apr 25, 2011 at 18:57
  • I need the name to support legacy code, in that I should be just using the class name directly via c.getClass().getName() but the rest of the code is not written to support this. Commented Apr 25, 2011 at 19:54

8 Answers 8

6

You could declare an abstract method in the parent and have each child implement the method to return the appropriate name, like this:

public abstract class Parent {
    public abstract String getName();
}

public class Child1 extends Parent {
    private static final String NAME = "Jon";
    public String getName() { return NAME; }
}

public class Child2 extends Parent {
    private static final String NAME = "Mary";
    public String getName() { return NAME; }
}
Sign up to request clarification or add additional context in comments.

Comments

3

Depending on what you're actually trying for, there are a couple of solutions. One is to make the child classes provide the name to the parent:

public abstract class Parent {
    protected Parent(String name) {
        this.name = name;
    }
    public getName() {return name;}
}
public class Child1 extends Parent {
    public Child1() {
        super("Jon");
    }

}
public class Child2 extends Parent {
    public Child2() {
        super("Mary");
    }
}

Another is to use method inheritance like Isaac Truett suggests.

1 Comment

This is it! My biggest concern with the way the Parent works is that I have to be more careful when calling functions that are not extended the Child which means, as far as I understand, that I'll have to use Getters/Setters from within the class itself, instead of accessing the member variables directly as direct access may result in getting the parents variables, as we've seen.
3

Create a static final String in each child that has your hard-coded name:

public class Child1 extends Parent 
{
    public static final String NAME = "Jon";
}

Comments

3

Use a method instead of a field (variable):

public abstract class Parent {
  public String getName() {
    return "the parent";
  }
}

public class Child1 extends Parent {
  public String getName() {
    return "Jon";
  }
}
public class Child2 extends Parent {
  public String getName() {
    return "Mary";
  }
}

In Java, at least, you can only override methods, not variables.

Another option would be to have Parent's constructor take the name as a parameter. If you do this it's best if Parent is abstract and all of the constructors take the name parameter. Then subclasses are required to pass in the name, which would typically be done something like this:

public class Child1 extends Parent {
  public Child1() {
    this("Jon");
    // ...
  }
}

Actually, even with the method overriding approach, it's nice if Parent is abstract so you can make getName() abstract.

3 Comments

Isn't this behaviour opposite to what is asked? Shouldn't simple public final getName() solve the problem?
@bbaja42 My interpretation of the question is that the OP wants getName() to return a different name based on the class of the instance it's called on. I'm not sure what the "opposite" of that is. The one thing in the question I didn't understand is the ".getClass()" in that last sentence. That's either a typo or what's being asked for isn't possible in Java.
after more careful reading of question; it seems you are right. By opposite I meant that different String is returned depending on type of objec.
1

The reason why your call to getName() doesn't return the child's name is because you've created a new variable call name within the child. Try this:

public class Child3 extends Parent{
    public String name = "Jon";

    public String getNames(){
        return super.name + " : " + name;
    }
}

You will see:

the parent : Jon

The correct way to set the name of the child into the parent's name variable is to say:

super.name = "Jon";

Comments

0

You need to overwrite the getName function in order to get the result you want. Because the new String name is not replacing the parent name so the getName function is actually reading the parent String

2 Comments

I noticed that, and I was hoping to keep as much code as possible in the Parent so I was searching for a way to avoid that. If that's how Java works then so be it, but I just had to ask you guys first.
@Tyler I believe StriplingWarrior's answer involves writing the least code in the subclasses.
0

Why not use the constructors?

public abstract class Parent {
    public String name = "the parent";
    public String getName() {
      return name;
    }
    public void setName(String s){
      name = s;
    }
}
public class Child1 extends Parent {
    public Child1() {
      setName("Jon");
    }
}
public class Child2 extends Parent {
    public Child2() {
      setName("Mary");
    }
}

Child1 c = new Child1();
c.getName(); 

// Prints 'Jon'

4 Comments

My example was abstracted but in reality the implementation you suggest would look like: PhotoClass pc = new PhotoClass("photo"), which just seems silly and the developer would have to know to always instantiate it with the word "photo" or else it won't work.
If you're saying that PhotoClass is analogous to Parent in your question, then no, you couldn't write new PhotoClass("Photo") because you declared it as abstract in your question. If Parent isn't abstract, that changes the question significantly.
@Tyler Then you've misread. The constructors josh.trow proposes for Child1 and Child2 do not have any arguments.
@Tyler Issac is correct, I don't propose passing a parameter in the constructor but rather calling a function within it. Personally, I detest calling a constructor with a parameter, I would rather instantiate with one call, let some internal logic take place, then use other method calls to precisely set up whatever I want.
0

You could do this using Java Reflection... but it's not a very clean way of doing things:

public abstract class Parent {
    public String name = "the parent";
    public String getName() throws Exception { return getClass().getField("name").get(this).toString(); }
}

Although I think Isaac's approach is the best way to approach the solution.

2 Comments

@Isaac Easy there killer, it's not like he proposed we all eat nothing but spinach from now on...although it is close :)
@josh.trow I would rather eat spinach (baby, with balsamic vinaigrette, please) than debug code that abuses reflection. Sadly, the latter occupation pays better. :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.