0

At this point i would exclude the inheritance.... So the question is about more like extend into a seperate class or into the class which should be extended, both play in the composition-league.

So Possibility 1:

class A
{
    //some behaviour + state
}

class B
{
    final A extend;

    //some injections or self-creating of A 
    public B(A extend)
    {
        this.extend = extend;
    }

    //some behaviour + state
}

Possibility 2:

class A
{
    //some injection, but its allowed that it may be null
    //in the case A is not extended
    B strategy;

    public B getStrategy()
    {
        return strategy;
    }

    //some behaviour + state
}

class B
{
    //some behaviour + state
}

So the question here is, what would you prefer 1 or 2.

There are a few more questions: On which areas are the class which extends an other class allowed to access. Only the public-things? I think if i want to extend something, its a inclusion. So that implies that the extendeing class must have access to all the internals of the other class. Also i think in the solution (1) i should add an getter to epose the extend in class B (in the case i dont want to override something, else i have to delegate all of it?) Apropos overriding: In (1) i cant do something like this.

Some thoughts about (1) and (2)

(1)

  • Override is possible
  • having a generic List with List a; a.add(b) isnt possible

(2)

  • Override isnt possible
  • the generic list is possible List a; a.add(a which could contain b) is possible
  • maybe you see there some kind of the component-design-pattern (known from games) in it.
  • it has a open-closed problem, cause every time i want to add something i have to touch the base-class
  • i could each extension let communicate with the other one (but in that case, can i still talk about that then i have still extensions?)

The main question is, would you do (1) or (2).
Subquestions: What is the extending class allowed to access from its base-class.

Maybe we have a class with 100 methods and i want to break that down into smaller classes. How would you do this? Would you break that down into a base and more extending classes/ which could be part of the base class (2) or extend it from outer (1), would you give them all access to all others?. I think a break down a big class which is very cohesive into smaller once, i need to use (2), because they all have to know all from the others. If i use a outer extend-version like in (1), the base dont have access to the parent. Maybe in that case we cant speak any more from extending, but more from how to organzize one big base-class into a lot of smaller one. Is that there allowed to access all of the others? And then i want to split again into smaller one, here i would have a big class-hirachie, and all of them must have access to all others.... so in that case i would violate the law of demeter, encapsulation and maybe a few more. how should I do it differently?

So one last question here: If i use a framework, library, then i also have often the same problem.

  • Extend it by version (1), while the base-class the lib/framework is
  • I want to configure it and use it then.

For both situations i use version (1), cause of course i cant modify the lib internaly like i must if i choose (2). But as i also said, often i only want to configure it or something like this. For example if i have a http-server-lib i want to start the server with certain parameters and so on. In that case i think we cant speak any more from extending but more from using?. The problem here is, after i started and configured it, i want to exposed it. The problem here is, i have a class which only functionality is having functionality and no state. So here im not sure where to put the code if i dont want to put the code into each client who wants to use the server, i only want to configure the server one time. So i have only a class with one method, for me its code which should not live in a class but as a function standalone, but maybe you have there some more ideas.

So the question is where i should locate, code the behaviour, (1) (2) maybe a 3 -> extra functions without classes, a 4 -> something else?

(If you think there are different question in one, then let me know, but i think its all very connected)

2

These two approaches look similar in surface but have some important differences:

  • option 1: A and B can have completely independent behaviors. B may reuse some behavior of A without outside world knowing.
  • option 2: B and A can have potentially independent behavior, although the naming strategy suggests that A’s behavior is influenced by B. A also exposes B’s behavior to the outside word via its getter.

So they address different design intentions. And have different consequences for their client:

  • in option 1, a client of B doesn’t have to know anything about A to benefit form the reuse of its behavior.
  • in option 2, a client of A may have to know B in order to use its exposed behavior.

In terms of coupling and dependency management, option 1 offers therefore more flexibility.

In terms of encapsulation, option 2 has a weakness: since B is publicly “leaked” (i.e. not kept private), a user of A may alter the state of B (keep in mind that java has reference semantic). This might influence the behavior of A in unexpected/untested ways.

Finally, you can infer that for option 1 you should not expose A. If you have a private member, keep it private.

About your more general question, whether the extending class should have access only to the public members of the extend class, the answer is: preferably, yes. In the context of inheritance, there are numerous debates about the use of protected members (i.e. not public, but accessible to the extending classes). Although I’m not dogmatic, the general advise is not to use protected members, because they are a source of nasty bugs in practice, and a breach of the history constraint of LSP. Even designers of popular languages express some regrets about such mixed access and recommend not to use it. So, chose either real private or real public.

Additional comment: the term “extend” does seem ambiguous here. In OOP, extending usually means to give the same interface and enrich it or its behaviors. In option 1 this would imply to reimplement the public metods of A in B, and either forwarding calls or enriching behavior. If you don’t, your approach should be called “reuse”. Furthermore, in Java extending means specializing through inheritance.

| improve this answer | |
  • to your additional comment: what you mean with "[...] to give the same interface and enricht it? " A interface has a defined behaviour?! I cant enrich it, i only can change the defined behaviour; but if i change the behaviour, where is there the enriching of it?. If i want to enrich it, i have to add more interfaces/methods to an existing interface, or not? And in that case, if have to make all public-things also public in the endproduct, see for that my next comment – Robin Kreuzer Jun 20 at 13:45
  • so in option 2, i want from the outside have a direct access to B-strategy. And if i see it as an extension, so its not really a strategy, but something from the class itself. That means the B-strategy should be able to change some state in A, and i have to make sure, that this approach dont influence the behaviour of A in an unexpected way. The same should also apply for option 1. If i dont override something, then i can expose A with a getter in B too – Robin Kreuzer Jun 20 at 13:49
  • So how you would refactor the implementation of a big interface, which have 100 methods into smaller one?, The public-stuff should be the same, or more or less the same, it should be accessable; maybe i have one container class at the end, which contains 30 sub-classes (my B-strategy), but i have to expose them all, cause i want to have acess to all public stuff the same way if i would have only 1 class with that 100 methods. Maybe you can add something to this into your answer and something to the question how to use/extend a lib/framework. Anyway your previous answer is already great. – Robin Kreuzer Jun 20 at 13:53
  • In inheritance and composition you always can enrich an interface. A well known example is the decorator pattern, the decorator being allowed to implement other interface, or implement a more specialised interface that extends a base interface – Christophe Jun 20 at 13:54
  • 1
    @RobinKreuzer let’s avoid a misunderstanding: option 1 & option 2 are not kind of decorators & mixins. I mentioned decorator to illustrate that interfaces can be enriched. And mixin not because of option 2, but what you explained you wanted to achieve with opt 2. About the 💯 refactoring and the framework extension: these are questions that are too broad with the few elements provided in your question. It’s as if you’d describe a nail/screw, I answer with hammer/screwdriver, and then you ask about making a wooden veranda :-) Make a different question with in-depth context so we can help :-) – Christophe Jun 20 at 17:03

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.