tdf#74702 1/2

Michael Stahl mst at libreoffice.org
Mon Jul 8 09:36:14 UTC 2019


On 06.07.19 19:59, Adrien Ollier wrote:
> Hello Community,
> 
> I am writing this very important e-mail because I need the collaboration 
> of each of you.
> 
> I am working on bug #74072 
> <https://bugs.documentfoundation.org/show_bug.cgi?id=74702> whose aim is 
> to remove the OutDevType enumeration. OutDevType was introduced to know 
> the real type of an OutputDevice 
> <https://docs.libreoffice.org/vcl/html/classOutputDevice.html> at any 
> moment because some functions need the real type of the OutputDevice.
> 
> But using this enum is not the good way for doing that. So far, I could 
> quite easily correct this in the OutputDevice's functions by introducing 
> virtual methods. There are still a few OutputDevice's methods that use 
> OutDevType (through GetOutDevType()) but the big majority of remaining 
> functions take an OutputDevice as argument and virtual functions can't help.
> The only good way for not using OutDevType can be summarized in this 
> simple sentence:
> "If a function needs to know the real type of an object, keep the real 
> type of the object."
> 
> Suppose we have the following hierarchy of classes:
> 
> class A {/* ... */};
> class B : public A {/* ... */};
> class C : public A {/* ... */};
> 
> And suppose we have the following function:
> 
> int g(A* pA);
> 
> But g behaves differently according to pA is a A*, a B* or a C*. Instead 
> of introducing an enum to know if pA is a A*, a B* or a C*, the good 
> solution is to have three functions:
> 
> int g(A* pA);
> int g(B* pB);
> int g(C* pC);

mixing ad-hoc and inclusion polymorphism in this way, i.e., overloading 
across subtypes, is a really bad idea.  (and the undisciplined 
overloading in languages like C++/Java is quite error prone in general 
and i'd rather discourage its use).

> 
> This requires to keep the real type of the variable object before calling g.
> So we must NOT write this:
> A* myVar = new B{};
> g(myVar); // calls g(A*)
> 
> Instead, we MUST write:
> B* myVar = new B{};
> g(myVar); // calls g(B*)
> 
> But if g() is called by a function f(), f() also requires to keep the 
> real type of the variable. And if f() is called by e(), e() also needs 
> to keep the real type of myVar. And can continue until the first 
> function a() which calls g() by waterfall effect.

which is of course silly because the result is quite contorted function 
abstractions and it's trivially easy to call the wrong (superclass) 
overload by mistake... so you agree that it's a really bad idea :)


More information about the LibreOffice mailing list