1

Say I have two classes abstract class A, class B extends A, and I let A has a private field of type List<String> to indicate that every subclass has a field of type List<String>(so I don't have to declare it for each subclass). Now if I want to let B to decide which implementation of List<String> it want to use(e.g. ArrayList<String>), then class A has to provide a constructor which accepts a parameter of type List<String>. By this design, if it's a large inheritance hierarchy, e.g. abstract A -> abstract B -> concrete C, in this scenario C will have to provide a constructor which resolves some implementations in both A and B:

class C extends B {
    // C's fields...

    // parameters for only C's fields, not inherited ones.
    C (...) { 

        super(/*fieldFromA:*/ new ArrayList<>(), /*fieldFromB:*/ new HashSet<>());
        // ^ this resolves A and B's field(s).

        // do other initializations...
    }

    // may also provide some parameters for fields inherited from A or B.
    C (list, set, ...) { 

        // use the parameters
        super(/*fieldFromA:*/ list, /*fieldFromB:*/ set); 

        // do other initializations...
    }
}

Is this a correct way to achieve what I stated in the title?

(I prefer to make the target field of A private because: (1) I don't want to provide public setter to the client, and (2) I don't like protected setter and protected fields, when it can be solved by constructor, but I don't know whether this is a good idea.)

  • 1
    ... is your question just "is this syntactically correct"? The compiler will tell you. But replacing meaningless class names like "A,B,C" by understandable names, and gving more context about the problem you want to solve would definitely increase the quality of this question by an order of magnitude. – Doc Brown Jun 9 at 9:57
2

If A provides a constructor that initializes List<String> then whatever calls that constructor gets to decide. B might do that and use ArrayList<String> or B might require that whatever implementation for it be passed in to its own constructor which would pass it on to A

I'm a big fan of overridable default values. So I'd lean towards a design that lets you choose, if you care, but defaults to something useful, if you don't.

  • So my example is not a bad idea? My friend told me that he didn't understand why I provide a constructor in A which includes the parameter List<String>, which should not be decided by the client, but I want each subclass of A can be default to different implementations. – Niing Jun 8 at 20:26
  • I have appended some words in my question, you may provide any advice about it. – Niing Jun 8 at 20:37
  • 1
    @Niing I don't know what problem you're trying to solve so my well considered expert opinion is "no idea". However, I will warn you that this could very well be the start of the yo-yo problem. – candied_orange Jun 8 at 20:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.