Question

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)

Was it helpful?

Solution

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.

Licensed under: CC-BY-SA with attribution
scroll top