|
From: Daniel Pitts on 28 Oct 2007 16:42 So, I know why it is bad for the "this" reference to escape the constructor, and that many people advocate using a static factory to help alleviate this problem, but it seems to me that you could run into the same kind of trouble. Any time you pass an instance to another class before it is fully initialized, you run the risk of that other class doing things that it shouldn't. As far as I know there isn't a way to ensure an atomic operation that expresses relationships between many objects to many other objects. Any setSomething method has the right to call any public method on the Something instance it is passed. It seems like it would be a burden to add a "completely initialized" runtime check on every behavior/knowledge querying method. The best it could do is throw an IllegalStateException. If you have a lot of places this could happen it become onerous to implement them all. I suppose you could create some sort of universal contract/convention that relationship builders (generally constructors and setters) don't do anything to the objects they receive or already know about, other than to save the given reference. This seems fragile at best, because the compiler has no way to enforce this, and someone may unwittingly access an object before all its required relationships are fully configured. This is especially troublesome with circular references, which I've been told should be avoided (probably for just this reason). Unfortunately, I don't see a rule that can be applied to systematically avoid circular during initialization. For my particular case. I have a class Robot, which has a Computer object, which has a Memory object and a Bus object. The Computer needs to know about the Robot, and visa versa. I can instantiate them separately, and then pass the references of each other to each other, but the Computer implementor would have to explicitly know that they can't access the Robot object during that reference exchange. Of course, I could just be confusing matters and making this into a bigger problem than it is. Any thoughts? -- Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>
From: Lasse Reichstein Nielsen on 28 Oct 2007 20:37 Daniel Pitts <newsgroup.spamfilter(a)virtualinfinity.net> writes: > This is especially troublesome with circular references, which I've > been told should be avoided (probably for just this reason). > Unfortunately, I don't see a rule that can be applied to > systematically avoid circular during initialization. For my > particular case. > I have a class Robot, which has a Computer object, which has a Memory > object and a Bus object. The Computer needs to know about the Robot, > and visa versa. Why? What is the relationship between Robot and Computer that the references model? Does that relationship really need to be created at the time the Robot and/or Computer is created? Can a computer not be moved to another computer? Are the Robot and Computer really separate entities, or does a Robot have a Computer aspect to it ... e.g., by implementing a Computer interface? > I can instantiate them separately, and then pass the > references of each other to each other, but the Computer implementor > would have to explicitly know that they can't access the Robot object > during that reference exchange. "Computer" sounds more generic than something that inherently knows about a Robot. > Of course, I could just be confusing matters and making this into a > bigger problem than it is. Any thoughts? I have this problem with MVC all the time :) /L -- Lasse Reichstein Nielsen - lrn(a)hotpop.com DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.html> 'Faith without judgement merely degrades the spirit divine.'
From: Roedy Green on 28 Oct 2007 21:50 On Sun, 28 Oct 2007 13:42:05 -0700, Daniel Pitts <newsgroup.spamfilter(a)virtualinfinity.net> wrote, quoted or indirectly quoted someone who said : >So, I know why it is bad for the "this" reference to escape the >constructor, and that many people advocate using a static factory to >help alleviate this problem, but it seems to me that you could run into >the same kind of trouble. There is a similar problem of calling virtual methods in constructors that may access uninitialised (but zeroed) fields. I think what Java aims to do is prevent you from doing anything that will crash the JVM. However, you are free to write programs that give meaningless results. The idea is they will put in a safety net whereever it is easy to do so, but feel no guilt about allowing you to write silly code. -- Roedy Green Canadian Mind Products The Java Glossary http://mindprod.com
From: Daniel Pitts on 29 Oct 2007 01:21 Roedy Green wrote: > On Sun, 28 Oct 2007 13:42:05 -0700, Daniel Pitts > <newsgroup.spamfilter(a)virtualinfinity.net> wrote, quoted or indirectly > quoted someone who said : > >> So, I know why it is bad for the "this" reference to escape the >> constructor, and that many people advocate using a static factory to >> help alleviate this problem, but it seems to me that you could run into >> the same kind of trouble. > > There is a similar problem of calling virtual methods in constructors > that may access uninitialised (but zeroed) fields. > > I think what Java aims to do is prevent you from doing anything that > will crash the JVM. However, you are free to write programs that give > meaningless results. > > The idea is they will put in a safety net whereever it is easy to do > so, but feel no guilt about allowing you to write silly code. > Calling possibly overridden methods is the (maybe not obviously) same as allowing a this reference to escape. In any case, I'm trying to avoid writing silly code. To me, silly means code that is too complex and too defensive, or code that is to simplistic and not "correct". Thanks, Daniel -- Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>
From: Dmitry A. Kazakov on 29 Oct 2007 04:52 On Sun, 28 Oct 2007 13:42:05 -0700, Daniel Pitts wrote: > So, I know why it is bad for the "this" reference to escape the > constructor, and that many people advocate using a static factory to > help alleviate this problem, but it seems to me that you could run into > the same kind of trouble. > > Any time you pass an instance to another class before it is fully > initialized, you run the risk of that other class doing things that it > shouldn't. As far as I know there isn't a way to ensure an atomic > operation that expresses relationships between many objects to many > other objects. The problem is not in whether operators are atomic or not. Clearly public operations have to honor object invariants. The problem is the language design and improper construction model of. While being constructed the object does not yet exist, hence a call to *any* its public method is illegal. As simple as that. When the specific object is constructed you can call any *specific* method, but it is still illegal to call any *dispatching* ones, any method potentially dispatching from inside. Only when the polymorphic object is finally constructed one can dispatch. This is the semantics of construction of a class instance, which you should mentally map onto an [admittedly inconsistent] implementation of in the given programming language (like C++ or Java). > This is especially troublesome with circular references, which I've been > told should be avoided (probably for just this reason). Unfortunately, > I don't see a rule that can be applied to systematically avoid circular > during initialization. No such thing can exist. It is as above. A reference may not exist before the target object. And the target object does not before construction. Hence, there cannot be any circular references upon initialization. Your problem is that semantically, you take a raw pointer (to specific object) and then cast it to a reference to a polymorphic object. That is semantically illegal, even if the compiler does not tell you so. > I have a class Robot, which has a Computer object, which has a Memory > object and a Bus object. The Computer needs to know about the Robot, > and visa versa. Then one object should be able to live without another. That would break the circle. You first create, say, computer without any robot and then attach a robot to it. Further, a robot should be functional when its computer has no robot attached. However, circular dependencies usually indicate a design problem. Perhaps you should reconsider your design. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de
|
Next
|
Last
Pages: 1 2 Prev: GUI design in simulation: or MVC pattern usefulness? Next: Scala and problems with OOP |