Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Choosing between extended classes inside constructor

I am writing a java (processing) library for unexperienced students, and am looking for the best architecture for implementing it. Initialization of an object should be as close as possible to this:

myObject = new General("type1");

Such that myObject will become an instance of Type1 which extends General:

class General {
  public General() {}
}

class Type1 extends General {
  public Type1() {}
}

class Type2 extends General {
  public Type1() {}
}

As far as I know, this isn't possible (choosing between extended classes during initialization), but I'm looking for the closest solution possible. So far, my best solution is to make a static initializer inside General:

class General {
  ...
  static General init (String type) {
    General temp;
    if (type.equals("type1") {
      temp = new Type1();
    }
    ...
    return temp;
}

and the initialization is:

General myObject;
myObject = General.init("type1");

This is far from ideal...

thanks.

like image 435
sgeiger Avatar asked Aug 06 '26 15:08

sgeiger


2 Answers

you can make a factory class that manages initialization. instead of doing it inside the parent.

    // Empty vocabulary of actual object
public interface IPerson
{
    string GetName();
}

public class Villager : IPerson
{
    public string GetName()
    {
        return "Village Person";
    }
}

public class CityPerson : IPerson
{
    public string GetName()
    {
        return "City Person";
    }
}

public enum PersonType
{
    Rural,
    Urban
}

/// <summary>
/// Implementation of Factory - Used to create objects.
/// </summary>
public class Factory
{
    public IPerson GetPerson(PersonType type)
    {
        switch (type)
        {
            case PersonType.Rural:
                return new Villager();
            case PersonType.Urban:
                return new CityPerson();
            default:
                throw new NotSupportedException();
        }
    }
}
like image 79
Yahya Shqair Avatar answered Aug 10 '26 12:08

Yahya Shqair


The State design pattern can be a solution here. Rather than the constructor argument changing the type of the object (which isn't possible) it can set a field of the object, to make it behave as if its type is different.

package stackoverflow.questions;

public class Main {
    private interface MyInterface {
        String foo();
        int bar();
    }

    private static class Type1 implements MyInterface {
        @Override public String foo() { return "lorem ipsum "; }
        @Override public int bar() { return 6; }
    }

    private static class Type2 implements MyInterface {
        @Override public String foo() { return "dolor sit amet"; }
        @Override public int bar() { return 7; }
    }

    public static class General {
        private final MyInterface type;

        public General(String type) {
            try {
                this.type = (MyInterface) Class
                        .forName("stackoverflow.questions.Main$" + type)
                        .getDeclaredConstructor().newInstance();
            } catch (Exception e) {
                throw new IllegalArgumentException("Invalid type: " + type);
            }
        }

        public String method1() { return type.foo(); }
        public int method2() { return type.bar(); }
    }

    public static void main(String... args) {
        General one = new General("Type1");
        General two = new General("Type2");
        System.out.println(one.method1() + two.method1());
        System.out.println(one.method2() * two.method2());
    }
}
like image 28
jaco0646 Avatar answered Aug 10 '26 11:08

jaco0646



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!