Prev: Lost in translation (with SPARK user rules)
Next: Sockets package in SPARK (Was: Lost in translation (with SPARK user rules))
From: Maciej Sobczak on 7 Jun 2010 08:17 On 7 Cze, 11:25, "Martin Krischik" <krisc...(a)users.sourceforge.net> wrote: > > Considering the performance aspect, the layout of variables within the > > object is determined *statically* [...] > Interesting opinion. Say we have [...] You are right here, I got confused by the low-level implementation details. There must be a run-time component of the access method for instance variables from virtually inherited classes. Mea culpa. I will still take the opportunity to twist my mistake :-) - take it as a proof that I have never explicitly used virtual inheritance in professionally written code, even though I *have* used multiple inheritance occasionally. Guess what - the default mechanisms always worked as I intended - this might be an indication that the whole problem is not nearly as dramatic as you portray it. In other words, I disagree with your statement that the behavior of C+ + in this area should be different. > > Again, that knowledge would not necessarily help them, as the use of > > virtual inheritance is not automatically justified. > > Like the use if virtual destructors is not automaticly justified? That's right. > Only: > count in your source the amount virtual destructors vs. non virtual > destructors. OK. Let's take something publicaly verifiable: the YAMI4 project, which contains some amount of C++ code (analyzed header files): - All destructors: 28 - Virtual ones : 6 Let's take the SOCI project for comparison: - All destructors: 61 - Virtual ones : 20 It looks like virtual destructors amount for some 20-30% of all in my code. > Why is what you need most not default? I find that what C++ offers in this area is what I need most of the time. Now I even have the scientific and statistical proof for this, as before this discussion I did not even know the real numbers. :-) I don't claim that my experiences are representative, but I will take the risk to claim that if you need all or most of your destructors to be virtual, then you are probably trying to write Java in C++. Now, to bring this discussion at least a bit back on topic, I think that Ada could offer similar mechanisms as C++. The reason is that the object model in both languages is very similar and in both cases based on value semantics. In particular, I find it a nuisance that controlled types must be tagged. -- Maciej Sobczak * http://www.inspirel.com YAMI4 - Messaging Solution for Distributed Systems http://www.inspirel.com/yami4
From: Dmitry A. Kazakov on 7 Jun 2010 08:26 On Mon, 7 Jun 2010 05:17:16 -0700 (PDT), Maciej Sobczak wrote: > In particular, I find it a nuisance that > controlled types must be tagged. Ditto, types where a class may root. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de
From: Martin Krischik on 7 Jun 2010 11:00 Am 07.06.2010, 14:17 Uhr, schrieb Maciej Sobczak <see.my.homepage(a)gmail.com>: > It looks like virtual destructors amount for some 20-30% of all in my > code. Now that is interesting. It means that most of your classes are final as the java guys would say. While I have always written under the premises that my classes might become child classes for something else. BTW: you are aware that if the parent class uses a virtual destructor then the child class does as well - even when not explicitly specified? > then you are probably trying to write Java in C++. I learned C++ before Java using IBM Open Class Library «http://en.wikipedia.org/wiki/IBM_Open_Class». Probably more then anything the OCL influenced my OO thinking. A string class with lazy copy, a great collection class which (optionality) implemented the observer notifier pattern, a database persistence object layer. Well and 90% of the classes descending form IVBase. Guess what the V stands for. There is a class overview here http://www.warpspeed.com.au/cgi-bin/inf2html.cmd?..%5Chtml%5Cbook%5CIBMVACPP%5CCPPCLRF.INF or here: http://caligari.dartmouth.edu/doc/ibmcxx/en_US/doc/hgref.htm And yes the OCL shares a lot with Java. The single base class for example, or a toString method for every class, or the use of interfaces. Martin -- Martin Krischik mailto://krischik(a)users.sourceforge.net https://sourceforge.net/users/krischik
From: Luis Espinal on 7 Jun 2010 14:30 In article <op.vdvcs3b5z25lew(a)macpro-eth1.krischik.com>, Martin Krischik says... > >Am 28.05.2010, 07:25 Uhr, schrieb Luis Espinal <Luis_member(a)newsguy.com>: > >> I don't think that is much of an issue. Mutability is. This is a big >> issue for >> Java as it has turned out. The commonly accepted best practice now is to >> mark >> variables and parameters as final unless you know before hand that you >> want to >> change them. > >Which only makes the reference to the variable un-mutable, not the >content. Yes. Absolutely and you are right. I think I should say that comment is wrt of Java default behavior towards variable/parameter declarations vs Scala's. So, what we are referring to here is not so much immutability of class instances (which would be the ideal... see below), but immutability of values and arguments within expressions (a practical concession given the limits of the language). The argument here is values that are immutable (either manually as in Java or by default as in Scala) leads to writing code based (or mostly based) on expressions. When done properly, it tends to be succinct and yet readable. >That combined with language which can do only pass by reference >for all complex types and a Clonable interface which was badly sorted out >gives you a language where the protection a getter function should give >you is just not there - unless you make it a habit to use «return x.clone >()» [1]. > It's not just Cloneable that we have to deal with. It's also when implementing Serializable. Or forced to rely on automatic garbage collection without having reliable finalizer methods. Not having the C++ equivalent of const member functions and const return types can be quite hurtful, too. >And if we are at it - setter functions should use «this.x = x.clone ()». >Those who did Ada or C++ know that. In Ada setter and getter functions >usually take a copy and in C++ setter and getter functions take a >reference to a constant object. That is: not the reference is constant - >the object itself is constant (un-mutable). > You are going to have forgive my C++/Ada peasantry since I haven't touched either for more than a decade (since I left grad school.) Why exactly would we want (in Java) to return a clone wrt to a setter/getter? I could understand *that* in C++ wrt to implementing a getter for an entity "A" that returns a modifiable copy/clone of "A". But in Java (where we have no guarantees when an object is going to be reclaimed), we simply cannot do that. By default, we have to assume that if a getter returns a reference to an instance of a class that is not immutable (.ie. extensions of java.lang.Number or String), then we have the ability to modify it (while still being part of the enclosing class exposing the getter method.) That's the default modus operandi. Anything else (returning a deep or shallow clone, for instance) has to be explicitly documented. As you pointed out, however, a good and valid criticism can be made on Java regarding 1) passing everything by value and 2) working with object references only. Without having the C++ equivalent of const member functions and const return types, it is impossible to syntactically enforce immutability. We can only do so in Java by convention and by structuring our classes as either mutable and immutable (the later being Scala's route.) >As it is most setter and getter functions in Java are placebos - they give >you you the feeling to do it the proper OO way but you are don't! > >Martin > >[1] provided the class at hand implements the Clonable interface property >and does indeed do full deep copy. I'm not sure I follow here either. I'm saying this genuinely, and I'd be happy to see your POV on this subject. To me a chain of calls P.getQ.getR...X.getY.getZ is simply a chain of messages from the caller to an given entity(Z) all the way through different contexts. The accessed attribute can be very primitive or complex, mutable or immutable, all that depending on the nature of the message and the nature of the receiving entity. That is, its complexity (or lack thereof) is implementation-specific, and thus hidden by these getter and setter methods. Whether it is immutable or if it permits mutability of one or all of its attributes, that's specific of the entity's public interfaces. I'd grant that it will be better, more syntactic, finer grained way of controlling mutability, but its presence is not necessarily required for object-orientation. I won't argue, however, the sad fact a lot of people in Java don't understand that, and they end up simulating goto-based programming with their poorly constructed classes :) - Luis Espinal. luis.espinal(a)gmail.com ps... I'll add to the discussion that one thing we sorely miss in Java is the ability to write nested functions as in Ada, Pascal and ALGOL. IMO they lead to cleaner, more organized code.
From: Martin Krischik on 8 Jun 2010 02:43
Am 07.06.2010, 20:30 Uhr, schrieb Luis Espinal <Luis_member(a)newsguy.com>: > In article <op.vdvcs3b5z25lew(a)macpro-eth1.krischik.com>, Martin Krischik > says... > Not having the C++ equivalent of const member > functions and const return types can be quite hurtful, too. cost is a reserved word in Java. That's for future use as keyword. So is goto ;-). > >> And if we are at it - setter functions should use «this.x = x.clone >> ()». >> Those who did Ada or C++ know that. In Ada setter and getter functions >> usually take a copy and in C++ setter and getter functions take a >> reference to a constant object. That is: not the reference is constant - >> the object itself is constant (un-mutable). >> > > You are going to have forgive my C++/Ada peasantry since I haven't > touched > either for more than a decade (since I left grad school.) Why exactly > would we > want (in Java) to return a clone wrt to a setter/getter? I thing this example should explain it: java.util.ArrayList evilChange = someInstance.getPreciousList (); evilChange.clear(); O course retuning a const would protect just as good and render better performance. Having immutable object like java.lang.String helps as well. > By default, we have to assume that if a getter returns a reference to an > instance of a class that is not immutable (.ie. extensions of > java.lang.Number > or String), then we have the ability to modify it (while still being > part of the > enclosing class exposing the getter method.) In Java. Most other OO languages see that differently. The OO principle is the the internal state of a class can only be changed true a setter. If I have a state called preciousList you should not be able to change preciousList using getPreciousList(). You should do so be using setPreciousList(), setPreciousList(int) or appendPreciousList(). Why? For example my class states are usually bound. If you get the list and change it behind my back the observers are never notified of change. The hole observer/notifier pattern collapses. And with it the model/view/controller pattern. And eh voila what is shown in the view is not what is stored data access object and a difficult to find bug in the middle. > That's the default modus operandi. Anything else (returning a deep or > shallow clone, for instance) has to be explicitly documented. This in my eye is turning a fault into a virtue. > only do so in Java by convention and by structuring our classes as either > mutable and immutable (the later being Scala's route.) immutable data access objects? >> As it is most setter and getter functions in Java are placebos - they >> give >> you you the feeling to do it the proper OO way but you are don't! > I'm not sure I follow here either. I'm saying this genuinely, and I'd be > happy to see your POV on this subject. > > To me a chain of calls P.getQ.getR...X.getY.getZ is simply a chain of > messages > from the caller to an given entity(Z) all the way through different > contexts. That's ok. What I argue is that the following should not be allowed: P.getQ.setR(…) It should be: q = P.getQ q.setR(…); p.setQ(q); And the simplest of all examples are bound properties (that's observer/notifier pattern for non Java developers). If you do the first then the observers of P are not notified. of the change to Q. I would not be surprised if observer/notifier was considered an anti pattern in Java [1]. That again would be turning a fault into a virtue. Observer / Notifier worked marvellously great in the IBM open class (C++). > ps... I'll add to the discussion that one thing we sorely miss in Java > is the > ability to write nested functions as in Ada, Pascal and ALGOL. IMO they > lead to > cleaner, more organized code. int f () { class c { int g () { … }; } c i = new c(); return i.g(); } just about as painful as using local packages to add static variables to Ada procedures. Martin [1] Like the singleton pattern. I read the rationale why singleton is considered an anti pattern and it was all about Java quirks which do not apply to Ada or C++. Still the Java advocates cry “anti pattern”. For me anti pattern need to be anti pattern in all (or at least most) programming languages. PS: I am doing my SCJD right now. I think the assignment has been specificity designed to make you hate Java. Or maybe I should not have chosen rmi over socket communication after all... -- Martin Krischik mailto://krischik(a)users.sourceforge.net https://sourceforge.net/users/krischik |