/* [Me] Traits do offer a decent fix for this issue: define a trait that offers a "get_data_x" function, and require that all types accessed through that trait get "data_x" from *somewhere* but don't worry about where. ...
[Cosic] I dont agree. Consider this example (Java code with additional rename keyword) ...
Clean, simple, readable. */
I like this one too. Now I feel like a county fair judge with a big appetite but no idea if one recipe is better than anoter.
/* I'm arguing that inheritance of state (and/or implementation) should be optional. Not obligatory, not forbidden, but optional. It's easy to add that to MI. */
Yep, I like this, *too*.
/* [Me] But what if D.method() needs A.method() to do something new?
[Cosic] You must be using Java. This requirement is easily added to MI, and, in fact, C++ already offers it ... */
Actually, I was thinking C++, but I know it's available in Java.
Here's the hypothetical:
class A
{ int a;
int aa;
public:
virtual void method(XML_document &doc)
{ doc.add_element(a).add_element(aa);
};
};
class B : public A
{ float b;
public:
void method(XML_document &doc)
{ doc.add_element(b);
A::method(doc);
};
};
class C : public B
{ std::string c;
public:
void method(XML_document &doc)
{ doc.add_element(c)
B::method(doc);
};
};
class D : public C
{ int d;
public:
void method(XML_Document &doc)
{/* For whatever reason, d must be placed between a and aa. what should I do? */
};
};
To me it looks like the problem is not in inheritance, but in how interfaces are designed in your example.
Your example is something like: There is class Stack, but for some reason it has no push method. Now that Stack is useless. You can't claim that's fault of inheritance.
The easiest fix it to provide getters for a and aa in class A.
You might have something else in mind, where, for whatever reason, it is not advisable to add getters for a and aa. But there are many other solutions, depending on what exactly the problem is.
/* To me it looks like the problem is not in inheritance, but in how interfaces are designed in your example. */
Well, I have to admit that I haven't run into this in practice either, so I may be jumping at shadows.
IMO, the problem is that once I've asked a class higher up in the hierarchy to handle something, I lose control until that class hands it back to me. Generally this is good as it permits me to ignore getter/setter methods for all parent classes. But it also means that I have no way of interrupting the call chain until it's finished.
FWIW, I believe traits allow make changes to the call chain (by swapping out A with A2 for D only). Then again, as I said, I haven't actually needed to do this, I just believe I may one day need to.
/* The easiest fix it to provide getters for a and aa in class A. */
But then I can't let C handle C-specific issues, same for B, same for A (once I call C::method() I'm resigned to letting it call B::method() and A::method()). There's a maintenance issue. Then again, for this to crop up, I may be at the wrong level of abstraction.
> But then I can't let C handle C-specific issues, same for > B, same for A (once I call C::method() I'm resigned to > letting it call B::method() and A::method()). There's a > maintenance issue. Then again, for this to crop up, I may > be at the wrong level of abstraction.
Oh, now I understand what you mean... nice example. Well, I agree, MI can't do what you want. Question is can traits do it. I don't really know, it's a complex issue, and probably depends on specific trait implementation.
This is not a subtyping issue, but subclassing. From MI perspective, what you want to do is change implementation of 'method' in D by overriding, but you want to keep some of implementation. This can only be solved if designer of class A predicted your need and wrote:
class A { int a; int aa; public: virtual void method(XML_document &doc) { default_method_impl(doc); } protected: virtual default_method_impl(XML_document &doc) { doc.add_element(a).add_element(aa); } } .. which enables you to override default_method_impl in class D.
This is a solution to your problem in MI world. But I dislike this solution because I don't like 'protected'. I have devised another mechanism that completely eliminates need for protected keyword. But again, the designer of class A must have predicted the need to inherit part of implementation.
I don't believe this is a serious issue with MI. You just can't say 'I want to inherit 3/4 of implementation'. It's either whole or none.
/* I don't believe this is a serious issue with MI. You just can't say 'I want to inherit 3/4 of implementation'. It's either whole or none. */
I have to admit that the example is somewhat contrived *and* that I've never had a set of requirements that mandated this. However, it was the first thing I thought of when I read up on traits. Rather, the *first* thing was contracts (especially post-condition checking), but that's because cdiggins put that in my head. The first thing I came up with myself was this.
Flat View: This topic has 35 replies
on 3 pages
[
«
|
123
]