From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-0.3 required=5.0 tests=BAYES_00, REPLYTO_WITHOUT_TO_CC autolearn=no autolearn_force=no version=3.4.4 X-Google-Thread: 103376,dbcfe2b0a74da57e X-Google-Attributes: gid103376,public,usenet X-Google-Language: ENGLISH,ASCII-7-bit Path: g2news2.google.com!news3.google.com!feeder1-2.proxad.net!proxad.net!feeder2-2.proxad.net!newsfeed.arcor.de!newsspool4.arcor-online.net!news.arcor.de.POSTED!not-for-mail From: "Dmitry A. Kazakov" Subject: Re: Inherited Methods and such Newsgroups: comp.lang.ada User-Agent: 40tude_Dialog/2.0.15.1 MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Reply-To: mailbox@dmitry-kazakov.de Organization: cbb software GmbH References: <1190060534.958182.51800@d55g2000hsg.googlegroups.com> <87tzptuhku.fsf@ludovic-brenta.org> <1190125656.071013.303640@22g2000hsm.googlegroups.com> <1ds7l1l7oeyrx.1cpsvrpkikour.dlg@40tude.net> <1190147965.676457.123000@d55g2000hsg.googlegroups.com> <1co37tau98gct.axsglmqh0xu9$.dlg@40tude.net> <1190213376.707449.146640@g4g2000hsf.googlegroups.com> <1fl2wnziigxfd.1fjbag2hh8sbc$.dlg@40tude.net> <1190239986.762473.204290@k79g2000hse.googlegroups.com> <1rw45b3rmvmcr$.1df4wst5oknbl$.dlg@40tude.net> <1190296353.624737.150940@y42g2000hsy.googlegroups.com> <11m13st1f92kf$.m8s6y8mc8ebk.dlg@40tude.net> <1190321119.206313.65290@57g2000hsv.googlegroups.com> <1190408526.100291.265040@50g2000hsm.googlegroups.com> <9ukf2wtqjs0q$.iuijmal4x56b$.dlg@40tude.net> <1190497995.498679.119190@19g2000hsx.googlegroups.com> Date: Sun, 23 Sep 2007 10:41:07 +0200 Message-ID: <1mw3qju08q8uj.sgzht7ld9ydc$.dlg@40tude.net> NNTP-Posting-Date: 23 Sep 2007 10:39:52 CEST NNTP-Posting-Host: af0e194a.newsspool3.arcor-online.net X-Trace: DXC=NZ91XAYBV?5kUFX=Y?aLP;McF=Q^Z^V384Fo<]lROoR1^;5]aA^R6>26bIf`kK7EQ<[6LHn;2LCV>[ On Sat, 22 Sep 2007 14:53:15 -0700, Maciej Sobczak wrote: > On 22 Wrz, 10:48, "Dmitry A. Kazakov" > wrote: > >>>> class T >>>> { >>>> T () { f(); g(); } >>>> void g() {} >>>> virtual void f() {} >> >>>> }; > >>> Not exactly. In the constructor of T, *this already has type T. >> >> But you objected that *this is specific. You claimed that it dispatches in >> f(), if it does then it is of T'Class. > > This concept has no meaning there. Which concept? 1. The concept of class? 2. The concept of class representative? 3. The concept of typing? > *this is of type T and dispatches to T::_(). I.e. T is a representative of the class of types which has a polymorphic subprogram with some name I cannot figure out. The subprogram is such that its body for some type xxx from the class is "T::_". This description is language-independent. >> When you claim that T has been constructed prior the body of T(), then the >> latter simply cannot be a constructor of T! > > It is a constructor, because the initializer list is part of T::T(). The body of T does not initialize "parts." > The point is that in the constructor's body the components (fields) > are already constructed Yes this is the point. > (the initializer list handles this) and this > fact makes it safe to use these fields. That is irrelevant. Relevant is whether the object is safe to use as T. > This is important - you can *use* the fields, because they were > already constructed. A pile of fields does not make it object. Again, it is either untyped, or else you are talking about another type: struct {...}. You have constructed "struct," a predefined container type, you didn't T. > It would not be possible if *this dispatched to Derived::f(), because > there the Derived's fields do not yet exist. = the polymorphic object is not yet constructed = the class is not yet constructed One dispatches only on a class (per definition polymorphic subprograms act on the class) >> It is plainly inconsistent. > > It is consistent - the dispatch will never trick you into using not- > yet-constructed fields. That you cannot run red light on a stool does not make the latter a drive assistant system. >> The point is that in NO typed language a constructor can be >> defined solely in the language terms. Constructors have to be generated >> "per magic." But the language shall provide hooks for user-defined >> insertions in the generated constructors at the points, where the type >> contracts are satisfied. Isn't it obvious? > > Makes sense. Isn't it true in what I describe? No it isn't, because you refuse to annotate the types involved. When I try to give an annotation, you answer that this is not C++. The point of inconsistency is that no annotation can be given. > The inconsistency can be found > under the assumption that types must be invariant. Types aren't invariant. You are free to construct new types. > But if we remove this assumption, then the inconsistency is gone. No. Assuming you are talking about mutating objects, it is inconsistent with the notion of typing. You move the mess onto the client, which now does not know what to expect from the object it deals with. If you constrain the mutation scale in *any* way, and tell the client about that, then this would *automatically* define the true type of the object, and all these fake types you are talking about would be just aberrations. >> Don't hurry, I can pass this as parameter: >> >> T() : A(this), B(this), C(this) {...} >> >> and enjoy all the mess. > > Yes. You can remove this by prohibiting the use of 'this' in the > initializer list (some compilers warn about it anyway). > It is formally allowed, because can be useful if handled with enough > care. Good intentions pave the road to hell. But returning back to the issue. What is the type of *this the constructor of A does observe? Can you name it? >>> Identifier is permanent and this allows me to say that the object >>> *persists* along the process (there is no object replacement, etc.). >>> The type evolves during this process. >> >> What does persist? What is an object? You said it has a name. I am excited, >> but it does not help me in any way. What can I do with the object through >> its wonderful name? If you say that I can take its address, then that >> means: the type (behavior) has the function &. If you say that I cannot >> take its address, then the type does not have &. Either or. You cannot have >> conditionally legal methods in a statically typed language. > > I don't get it. You can call & on the type, unless operator& is > private. Which type? You said that the only thing objects have for sure is their names. Period. No types, no operations. >>> What about growing up? >> >> The type is Human. Height is an attribute of. > > I'm not talking about getting higher, but about growing up. > Human has subclasses Child and Adult. Presumably they can do different > things. :-) > > So - what about growing up? The attribute Age. > The only way to grow up the child in Ada and C++ is to kill a child > and resurrect it as an adult, reshuffling all necessary references in > the system so that they point to the new entity. > Not funny. But alas real, our cells get replaced as we grow. The point is that there are two parties in any contract. You cannot consider an object isolated from the clients of. If your client is a crocodile, then you are meat, adult or child becomes just a matter of taste... >> Actual type /= the type. The type = a common denominator of the behavior of >> "all objects like this." When you say that the behavior changes in a way >> the you cannot identify anything common, then it is "strongly" untyped [and >> absolutely useless too]. If you say that you can determine something like >> "actual" type, then it is "weakly untyped." Any such system can be made >> "strongly typed," by introducing methods like . Here >> is defined on the true type. "Actual type" is just the type >> of the result of the method and it yields *another* object. >> In cannot be the same object, because the types differs. If they differ >> then equivalently there exists a method you can apply to one, but not to >> another. For this method you cannot say if it were legal to apply it to the >> object that has both types. > > No. dynamic_cast gives another view on the same object. It does not > give another object. So you want to introduce views. There are object and views of. Care to define a difference, in terms *types* of course? (:-)) > You talk with someone over the phone. At some point you discover that > it's an adult, then you agree with him (dynamic_cast) that from now on > you can talk like adults. It's still the same person, you just know > more about him. Good example. We talk over a communication protocol, which itself is an object. Yes, there will be another protocol instance after handshaking. Of course we could design the protocol level as a parameter. But then, firstly, that would not make it a different type, and secondly, that could be an unsafe design, as we could forget about the constraint and get an exception. >>> Because the language recognizes the fact that construction/destruction >>> does not happen immediately and it is a "build-up" process. Assignment >>> is performed on the object that is already "established". >> >> You introduce many new terms: "immediately," "built-in," "established." >> Why these should be relevant to a type system? Do we need such complexity? > > As long as things don't happen "immediately", yes. > Without this "complexity" you get real complexity with dispatching to > vacuum. Nope, it is crystal clear in vacuum: no class, no dispatch. Type and only type have to tell what's going on. >> And what does prevent you from accepting the proposition that no object >> exists prior its construction? [...] > It's > after the constructor finishes when the clients can use the object via > its public interface. From their point of view the object exists after > the constructor finished. From the constructor point of view, the > fields exist before the constructor's body is executed. Easy. = you shall not use any public interface methods from the constructor's body => C++ is inconsistent allowing this. ---------------- Just annotate types. Fields construction does struct {...}. No less, no more. You can access fields because struct {...} has been constructed. You cannot use anything from T / struct {...}, because T is not yet constructed. (/ denotes set subtraction). The object of struct {...} does exist. The object T does not. Disagree? -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de