Java Inheritance... Confused - java

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

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; }
}

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.

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";
}

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.

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";

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

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'

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.

Related

Java code example for read only interface pattern

Consider the following code for a read only interface pattern in Java:
package package2;
public interface AccountsReadOnly {
public String getValue();
}
package package1;
import package2.AccountsReadOnly;
class Accounts implements AccountsReadOnly {
private String name;
public Accounts() {
name = "unknown";
}
public String getValue() {
return name;
}
public void setValue(String name) {
this.name = name;
}
}
package package1;
public class Manager {
Accounts allAccess;
public Manager() {}
}
package package2;
public class Employee {
public AccountsReadOnly accountReadOnly;
public Employee() {}
}
public class Demo {
public static void main(String[] args) {
Manager m = new Manager();
Employee e = new Employee();
Accounts a = new Accounts();
m.allAccess = a;
m.allAccess.setValue("Andrew");
System.out.println(m.allAccess.getValue());
e.accountReadOnly = a;
System.out.println(e.accountReadOnly.getValue());
}
}
I can't understand this line as this is the first time for me to see this format:
m.allAccess.setValue("Andrew");
Is it possible to use instead of this line since they have the same reference?
m.setValue("Andrew");
Is m.allAccess a reference of the object?
Is it possible to use instead of this line since they have the same reference?
no, m.setValue("Andrew"); does not work, because the Manager-class has no function setValue
Is m.allAccess a reference of the object?
yes, allAccess references the Account-object which is set in this line: m.allAccess = a;
The getValue and setValue methods should really be named getNameand setName, because that what they do. setValueshould return a value, e.g. the account's balance.
Also nameis not read-only if you have a setter for it.

How to return an object from parent class with type of Impl class?

I want to provide all implementation classes a default method that initializes the parent fields with default values. So I don't have to redefine those initialization within each Impl class:
public abstract class Parent {
private String name;
public static Parent defaultParent() {
Parent parent = new Parent();
//fill default field values
parent.name = "default name";
return parent;
}
}
public class Child extends Parent {
}
Now I can call Child.defaultParent(). But that would return me an object of type Parent. Is it possible this way to having the object being a Child object implicit? So that the defaultParent method always returns a type of the implementation class?
Maybe with java 8, functional interfaces or similar?
Here's one way to do it with Java 8:
public abstract class Parent {
private String name;
public static <T extends Parent> T defaultParent(Supplier<T> constructor) {
T parent = constructor.get();
//fill default field values
parent.name = "default name";
return parent;
}
}
public class Child extends Parent {
}
You can call the static method like this:
Child c = Parent.defaultParent(Child::new);
Or you can just use a constructor overload instead of a static factory method:
public abstract class Parent {
private String name;
public Parent(boolean useDefaults) {
if (useDefaults) {
//fill default field values
this.name = "default name";
}
}
}
public class Child extends Parent {
public Child(boolean useDefaults) {
super(useDefaults);
}
public Child() {
super(false);
}
}
This is what constructors were made for.
abstract class Parent {
private String name;
protected Parent(String name) {
this.name = name;
}
protected Parent() {
this("default name");
}
}
class DefaultChild extends Parent {
public DefaultChild() { super(); }
}
class CustomChild extends Parent {
public CustomChild(String value) { super(value); }
}
Everything else is just a fancy init method which is inferior to constructors because you can for example no longer assign values to final fields.
abstract class Parent {
private String name;
protected void init() {
this.name= "default name";
}
// or
protected static void init(Parent parent) {
parent.name = "default name";
}
}

POJO multiple-hierarchy Builder

I'm trying to achieve a hierarchy of builder with more than 3 levels.
Something like:
public abstract class ElementBuilder {
protected String name;
public ElementBuilder setName(String name) {
this.name = name;
return this;
}
}
public abstract class OperationBuilder extends ElementBuilder {
protected String attribute;
public OperationBuilder setName(String attribute) {
this.attribute = attribute;
return this;
}
}
public abstract class FilterBuilder extends OperationBuilder {
....
}
The problem is that when I call an operation of the super class it's returning a builder of the that class. I don't want to duplicate the setter method in each child, cause it maybe contain some logic.
I tried using generics but I could not achieve it in a clean way.

Declaring a nested class in Java

I'm a bit confused with subclasses.
Here's my code:
public class MedHistory {
private String grafts;
private String allergies;
private String diseases;
private String surgeries;
private String medicalTreatment;
//Constructors (#2)
public MedHistory(String allergies, String diseases, String grafts,
String treatments, String surgeries) {
this.allergies=allergies;
this.diseases=diseases;
this.grafts=grafts;
this.medicalTreatment=treatments;
this.surgeries=surgeries;
}
public MedHistory() {
this.allergies="";
this.diseases="";
this.grafts="";
this.medicalTreatment="";
this.surgeries="";
}
//Getters
public String getGrafts() {
return grafts;
}
public String getAllergies() {
return allergies;
}
public String getDiseases() {
return diseases;
}
public String getSurgeries() {
return surgeries;
}
public String getMedicalTreatment() {
return medicalTreatment;
}
//Setters
public void setGrafts(String grafts) {
this.grafts = grafts;
}
public void setAllergies(String allergies) {
this.allergies = allergies;
}
public void setDiseases(String diseases) {
this.diseases = diseases;
}
public void setSurgeries(String surgeries) {
this.surgeries = surgeries;
}
public void setMedicalTreatment(String medicalTreatment) {
this.medicalTreatment = medicalTreatment;
}
public class FemMedHistory extends MedHistory {
private List<Birth> births = new ArrayList<Birth>();
//Constructors (#2)
public FemMedHistory(String allergies, String diseases, String grafts,String treatments, String surgeries, List<Birth> birthlist) {
super(allergies,allergies,grafts,treatments,surgeries);
this.births=birthlist;
}
public FemMedHistory() {
super();
this.births=null;
}
//Getter
public List<Birth> getBirths() {
return this.births;
}
//Setter
public void setBirths(List<Birth> list) {
this.births=list;
}
}
}
When I try to create an new FemMedHistory object like this:
List<Birth> list = new ArrayList<Birth>();
list.add(new Birth(new GregorianCalendar(2011,4,10),"kaisariki",4));
FemMedHistory female = new FemMedHistory("allergia2","astheneia2","emvolia2","farmekeutiki agwgi2", "xeirourgeia2", list);
I get the error:
No enclosing instance of type MedHistory is accessible. Must qualify
the allocation with an enclosing instance of type MedHistory (e.g.
x.new A() where x is an instance of MedHistory).
So, which is the right way to use a subclass?
When you declare a nested class it only available through the Outer class.
To access it outside, you will need to either make the FemMedHistory class static.
public static class FemMedHistory extends MedHistory {...}
access it through the MedHistory class
MedHistory.FemMedHistory myMedHistory = ...
or declare it in it's own Java file.
You have declared your subclass as an inner class, which means that you can't create an instance of it without first creating an instance of the containing class.
The most common way to solve this is to declare it as a separate class, which would get rid of your error.
Long story short: cut all the FemMedHistory code and paste it into FemMedHistory.java. The way it is now you have involved Java concepts which you have not yet mastered. Also, that class really does belong in a separate file.

Factory class design issue in java

I have two classes
public class PrepaidPackage {
private String name;
private String serviceClassID;
private boolean isTranferable;
public boolean isTranferable() {
return isTranferable;
}
public void setTranferable(boolean isTranferable) {
this.isTranferable = isTranferable;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getServiceClassID() {
return serviceClassID;
}
public void setServiceClassID(String serviceClassID) {
this.serviceClassID = serviceClassID;
}
}
other class is
public class PostpaidPackage {
private String name;
private boolean isTranferable;
public boolean isTranferable() {
return isTranferable;
}
public void setTranferable(boolean isTranferable) {
this.isTranferable = isTranferable;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
I want to create a factory class which on base of package type create relevant class. But if you look at above clasess they dont have same type of methods and variables. So please guide how create interface or abstract class for above class?
Now factory will return class name Package. Would i able to call methods which are not present in other class.
Updates
Please suggest if i break my package into two classes like
public abstract class MyPackage {
public abstract PackageSpec getSpec();
public abstract PackagePrepaidDetails getDetail();
}
Now common attributes will be in PackageSpec and prepaid stuff in packageDetails.
Its kind of abstract factory pattern.
public class PrepaidPackage extends MyPackage{
PackageSpec spec;
public Spec getSpec() {
spec = new PackageSpec();
spec.setTranferable(true)
spec.setName("abc");
return spec;
}
public PackagePrepaidDetails getDetails() {
details = new PackagePrepaidDetails ();
details.setServiceClassID(123)
return details;
}
}
public class PostpaidPackage extends MyPackage{
PackageSpec spec;
public Spec getSpec() {
spec = new PackageSpec();
spec.setTranferable(true)
spec.setName("abc");
return spec;
}
}
I recomment you to have an interface if you don't have already. You do not neccessarily need it, but it is a good practice if they are so similar:
public interface Package {
public boolean isTranferable();
public void setTranferable(boolean isTranferable);
public String getName();
public void setName(String name);
}
Then in your calling code, you have a Package from your factory and:
Package p = myFactory.nextPackage(); // or something
if (p instanceof PrepaidPackage) {
PrepaidPackage prepaid = (PrefpaidPackage)p;
// and do the thing you want
} else if (p instanceof PostpaidPackage) {
PostpaidPackage postpaid = (PostpaidPackage)p;
// amd do the other things
}
Thing you are recommended to llok into is the instanceof operator and type casting.
A quick fix, not an ideal one is to have an interface that represents all the methods in the Prepaid class and leave them unimplemented in the Postpaid. That will solve the problem in the short term. I would suggest that you have a relook of the classes and the usages to avoid unimplemented methods in the code.
Well for an abstract super class you have to group everything common to both :
public abstract class MyPackage { // not sure you can call a class just "Package"
private String name;
private boolean isTranferable;
public boolean isTranferable() {
return isTranferable;
}
public void setTranferable(boolean isTranferable) {
this.isTranferable = isTranferable;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
then both inherits from it (the first adds serviceClassID and the second nothing)
your factory function will return a MyPackage (or AbstractPackage, whatever), but to access the specific function you'll have to cast after an instanceof test.
Two possible design choices you can make:
Have the prepaid package extend
postpaid package and your factory
then returns objects of type
postpaid package, the code which
calls the factory is then
responsible for inspecting the type.
Have a package interface which
defines all of the methods and have
postpaid package define the methods
to throw an
UnsupportedOperationException (ala
the way collections defines some
operations as optional.) or return
some kind of sentinel value (i.e. null)
For either of the above you could add another method getType() which returns an enum of the various package types you wish to implement, and this could then be used in the code that accesses the factory objects to determine which methods are available.

Categories

Resources