0

Say I have a class for Person which I want to implement as a static factory:

public class Person {
    private String name;
    private Double heightInMeters;
    
    private Person(String name, Double meters) {
      this.name = name;
      this.heightInMeters = meters;
    }
  
    public static Person fromNameAndCentimeters(String name, Double centimeters) {
      return new Person(name, centimeters/100.0);
    }
  
    public static Person fromNameAndInches(String name, Double inches) {
      return new Person(name, inches/3.28);
    }
  
    public string toString() {
      return "My name is " + name + " and my height in meters is " + heightInMeters;
    }
}

But I also have a nearly identical class Jeff for which I want to have slightly different factory methods:

public class Jeff {
    public static final JEFF_NAME = "Jeff";

    private String name = JEFF_NAME;
    private Double heightInMeters;
    
    private Jeff(String name, Double meters) {
      this.name = name;
      this.heightInMeters = meters;
    }
  
    public static Jeff fromCentimeters(Double centimeters) {
      return new Jeff(name, centimeters/100.0);
    }
  
    public static Jeff fromInches(Double inches) {
      return new Jeff(name, inches/3.28);
    }
  
    public String toString() {
      return "My name is " + name + " and my height in meters is " + heightInMeters;
    }
}

Clearly, Jeff and Person are related, and I want to do something like

public printIntroduction(Object somebody) {
    System.out.println(somebody);
}
printIntroduction(Person.fromNameAndInches("Bob", 65))
printIntroduction(Jeff.fromInches(60))

My first thought was to have Jeff inherit from Person - but child classes inherit static methods, and I don't want Jeff to have fromNameAndInches. What's the best way to go about this?

mdong
  • 345
  • 3
  • 10
  • What's the problem you're trying to solve? – shmosel Feb 17 '22 at 02:52
  • 2
    Have a BasePerson class which does not contain what you don't want, Both Person and Jeff can inherit from BasePerson – Scary Wombat Feb 17 '22 at 02:53
  • 1
    Part of the problem is that the factory methods are going to have similar logic in them and I'd like to somehow share that as well. Should shared logic between factory methods be spun off into another class as well? – mdong Feb 17 '22 at 03:15
  • You can create a factory class instead of using static methods. – shmosel Feb 17 '22 at 03:16
  • Feel free to ask any question. If my reply helps then you can upvote or mark it as an answer to simplify the future search of other users. Pelase, see [How does accepting an answer work?](https://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work) – StepUp Feb 23 '22 at 15:05

1 Answers1

0

I am trying to use inheritance when derived classes should have the same behavior like base class. So the public methods should be the same in base and derived classes. So, abstract class should define behavior, and the derived classes should implement that behavior.

But, there is no the same behavior in your example classes. So we cannot use inheritance here. However, we can improve code by reducing duplication of code of conversion to meters:

public class Conversion
{
    public double FromCentimetersToMeters(double centimeters) 
    {
        return centimeters / 100.0;
    }


    public double FromInchesToMeters(double inches)
    {
        return inches / 3.28;
    }
}

and then Person will be looked like this:

public class Person
{
    public string Name { get; private set; }

    public double Height { get; private set; }


    Conversion conversion = new Conversion();


    public Person(string name, double height)
    {
        Name = name;
        Height = height;
    }


    public Person FromNameAndCentimeters(string name, double centimeters)
    {
        return new Person(name, conversion.FromCentimetersToMeters(centimeters));
    }

    
    public Person FromNameAndInches(string name, double inches)
    {
        return new Person(name, conversion.FromInchesToMeters(inches));
    }
}

and Jeff class:

public class Jeff
{
    public string Name { get; set; } = "Jeff";


    public double Height { get; private set; }


    Conversion conversion = new Conversion();


    public Jeff(double height)
    {
        Height = height;
    }


    public Jeff FromCentimeters(double centimeters)
    {
        return new Jeff(conversion.FromCentimetersToMeters(centimeters));
    }


    public Jeff FromInches(double inches)
    {
        return new Jeff(conversion.FromInchesToMeters(inches));
    }
}

And then you can easily write unit tests for Conversion class to check whether the logic of conversion is correct.

StepUp
  • 36,391
  • 15
  • 88
  • 148