digitalmars.D - Hijacking
- Walter Bright (64/64) Aug 05 2007 I want to continue a bit in the Overloading/Inheritance thread which is
- Chris Nicholson-Sauls (9/86) Aug 05 2007 Thank the heavens for D's modules and FQN's. :) You've got that
- kris (12/90) Aug 05 2007 Walter:
- Walter Bright (6/18) Aug 05 2007 That is a good point. The reason I haven't added it is because I'm not
- Mike Capp (4/8) Aug 05 2007 C# has this rule, and based on 3-4 years of using it I'd say it's fine. ...
- Jarrett Billingsley (6/10) Aug 05 2007 If anything's annoying, it's when that kind of hijacking happens (I've h...
- kris (8/28) Aug 06 2007 Let's put it this way: I have a personal and quite open dislike for
- Walter Bright (2/4) Aug 06 2007 I'll put it in as a warning in the next update, and we can try it out.
- eao197 (30/45) Aug 06 2007 Eiffel has same feature for more than 20 years and it really works :)
- Walter Bright (4/5) Aug 06 2007 Eiffel has many good ideas, but we must be careful thinking of Eiffel as...
- eao197 (34/39) Aug 06 2007 as =
- Charles D Hixson (24/30) Aug 06 2007 My suspicion of the reason that Eiffel failed to catch on is
- Walter Bright (7/9) Aug 06 2007 For a complex thing like a language, it can be really hard to pin down
- Regan Heath (3/23) Aug 06 2007 My vote was, and still is, for 'override' to be mandatory.
- Don Clugston (3/29) Aug 06 2007 Me too. Note that since you can use 'override { }' or 'override:', it's ...
- Sean Kelly (4/6) Aug 06 2007 How does "override:" work with other properties used as labels? Is it
- Walter Bright (2/4) Aug 06 2007 It adds to them.
- Sean Kelly (3/8) Aug 06 2007 So is there anyway to disable "override:" once set?
- Chris Nicholson-Sauls (11/22) Aug 06 2007 Since there is no "not an override" keyword, I would wager there isn't.
- Sean Kelly (4/8) Aug 06 2007 Same here. Using "override:" doesn't seem feasible in all but the
- =?ISO-8859-1?Q?Julio_C=E9sar_Carrascal_Urquijo?= (11/22) Aug 07 2007 Chris Nicholson-Sauls wrote:
- Walter Bright (2/10) Aug 06 2007 No.
- Frank Benoit (4/7) Aug 06 2007 As said in my posting
- Robert Fraser (3/12) Aug 06 2007 votes++;
- Bruno Medeiros (6/9) Aug 06 2007 I don't think the mainstream opinion in Java is that checked exceptions
- Walter Bright (7/14) Aug 06 2007 It's not a great analogy, because there are very good technical
- Rioshin an'Harthen (7/9) Aug 06 2007 Exception specification *is* a good idea. Although I do hate it - try to...
- Nick Sabalausky (9/19) Aug 06 2007 Not to start a big big debate on it, but my own personal feeling on that...
- Chris Nicholson-Sauls (10/32) Aug 06 2007 I didn't mind it at first, in that the Java compiler would then let me
- Robert Fraser (2/37) Aug 06 2007 I'd like it to be required in the method where the exception is thrown f...
- Bill Baxter (6/26) Aug 07 2007 I agree with this 100%. With check exceptions it just becomes too
- Bruno Medeiros (48/78) Aug 08 2007 Interesting thing I'd like to mention, again about how IDEs affect the
- eao197 (41/113) Aug 08 2007 I don't agree (almost complitely). Checked expession is not simply
- eao197 (56/75) Aug 08 2007 =
- Christopher Wright (8/13) Aug 09 2007 The compiler can support this. It'd have to add more metadata to
- eao197 (40/52) Aug 09 2007 + =
- Bruno Medeiros (7/111) Aug 10 2007 I don't see how that is disagreeing with what I said before. Note that
- eao197 (10/15) Aug 10 2007 Umm... I'm sorry, I thought that 'ExceptionAdapter.unchecked(fe)' simply...
- Bruno Medeiros (6/26) Aug 10 2007 It fixes it well enough for me. :)
- 0ffh (4/8) Aug 06 2007 Hmmmm... even I think that requiring the override keyword is okay,
- BCS (3/26) Aug 06 2007 How hard would it be to put a command line flag on the 2.0 version that ...
- Bill Baxter (10/30) Aug 07 2007 Although, I generally like the idea, I fear that requiring 'override'
- Walter Bright (4/7) Aug 07 2007 I didn't think of that.
- Chris Nicholson-Sauls (47/56) Aug 07 2007 There are probably on two likely scenarios for that:
- Reiner Pope (27/61) Aug 08 2007 Interesting point. I think, however, that an explicit solution which
- Chris Miller (1/4) Aug 06 2007 I'm for this. I feel funny when I don't use "override".
- Regan Heath (3/3) Aug 06 2007 This post looks like a prime candidate for an article page on the D
- Ender KaShae (2/17) Aug 06 2007 if the function is overrided ONLY when the override keyword is there wou...
- Derek Parnell (6/10) Aug 06 2007 I'm just wondering what the NSA is making of this discussion :)
- Walter Bright (3/11) Aug 06 2007 Hopefully, they'll analyze the site, get excited about D, and use D for
- BCS (5/19) Aug 07 2007 Fat chance, most of D's advantages don't exist in under ~5000 LOC and an...
- Sean Kelly (4/24) Aug 07 2007 I'd think DBC would be a perk, if nothing else. Assuming the NSA
- janderson (3/30) Aug 07 2007 I thought NSA used ADA it was designed for such purposes.
- BCS (3/37) Aug 07 2007 The only experience I have (yes I do have a tiny bit) is in C and is onl...
- Sean Kelly (8/20) Aug 08 2007 By my understanding, Ada was largely intended for robust systems
- Kristian Kilpi (43/107) Aug 10 2007 The old aliasing trick will still cause problems.
- Walter Bright (4/32) Aug 10 2007 I don't think this is a problem, because the B author explicitly and
- Regan Heath (10/43) Aug 11 2007 Yes and no.
- Chris Nicholson-Sauls (23/72) Aug 11 2007 Honestly, we need some ability to specify more of a function/method's si...
I want to continue a bit in the Overloading/Inheritance thread which is getting a little long, on a closely related issue which I find to be important, but so rarely referred to that I had to come up with a name for it - hijacking. Hijacking is when code A depends on B, and then when seemingly unrelated code C is modified, then A's behavior silently changes. Here's an example from C++: --A.h-- void foo(long i); --B.c-- #include "A.h" #include "C.h" ... foo(3); // calls A's foo(long) -------- Let's say A.h and C.h are developed by different people. In C.h, the developer adds: --C.h-- void foo(int i); ----- This does something completely different from A.h's foo(long), because they just happened to share the same name. Now, when B.c is recompiled, it's call to foo is silently *hijacked* by C.h's foo. Because of C++'s overloading rules and lack of modularity, there's no way to programmatically defend against this. Instead, one has to rely on coding conventions (such as using a unique package prefix name on all symbols, like A_foo() and C_foo()). So how does this relate to the overloading/inheritance issues? Consider: ----A.d---- class A { ... } -----B.d---- import A; class B : A { void foo(long); } ... void bar(B b) { b.foo(3); // calls B.foo(long) } ---- Let's say A.d comes from some third party library. Now the developer of A decides to add some functionality to class A, and adds the member function foo(int): ----A.d--- class A { void foo(int); } ------------ Now our hapless B programmer has his calls to B.foo(long) silently hijacked to A.foo(int) (under Java rules). I don't see any reasonable way for B to defend against this. Certainly, developer A doesn't have any idea who is deriving from A (and that's the point of polymorphism) - but should he be disallowed from adding *any* method names? And the hapless B developer, he wrote class B years ago and no longer quite remembers how it works, he just recompiles it and now it silently fails. So, this is one case where I feel C++ got it right, and Java didn't. (P.S. It's not a compiler implementation issue, nor is it a runtime performance issue.)
Aug 05 2007
Walter Bright wrote:I want to continue a bit in the Overloading/Inheritance thread which is getting a little long, on a closely related issue which I find to be important, but so rarely referred to that I had to come up with a name for it - hijacking. Hijacking is when code A depends on B, and then when seemingly unrelated code C is modified, then A's behavior silently changes. Here's an example from C++: --A.h-- void foo(long i); --B.c-- #include "A.h" #include "C.h" ... foo(3); // calls A's foo(long) -------- Let's say A.h and C.h are developed by different people. In C.h, the developer adds: --C.h-- void foo(int i); ----- This does something completely different from A.h's foo(long), because they just happened to share the same name. Now, when B.c is recompiled, it's call to foo is silently *hijacked* by C.h's foo. Because of C++'s overloading rules and lack of modularity, there's no way to programmatically defend against this. Instead, one has to rely on coding conventions (such as using a unique package prefix name on all symbols, like A_foo() and C_foo()).Thank the heavens for D's modules and FQN's. :) You've got that situation covered.So how does this relate to the overloading/inheritance issues? Consider: ----A.d---- class A { ... } -----B.d---- import A; class B : A { void foo(long); } ... void bar(B b) { b.foo(3); // calls B.foo(long) } ---- Let's say A.d comes from some third party library. Now the developer of A decides to add some functionality to class A, and adds the member function foo(int): ----A.d--- class A { void foo(int); } ------------ Now our hapless B programmer has his calls to B.foo(long) silently hijacked to A.foo(int) (under Java rules). I don't see any reasonable way for B to defend against this. Certainly, developer A doesn't have any idea who is deriving from A (and that's the point of polymorphism) - but should he be disallowed from adding *any* method names? And the hapless B developer, he wrote class B years ago and no longer quite remembers how it works, he just recompiles it and now it silently fails. So, this is one case where I feel C++ got it right, and Java didn't. (P.S. It's not a compiler implementation issue, nor is it a runtime performance issue.)Alright. I can't argue against that one little bit. I will mention for completeness the option of using an L suffix to explicitly state you want a long... but then there's no analog for explicit int/short/byte, so the problem still exists in any case other than ambiguity against long. (Yes there's cast()... but ew.) -- Chris Nicholson-Sauls
Aug 05 2007
Walter: There's a related problem where a public method is added to a base-class A (as in your example) but where the signature is *exactly* that of one existing in derived class B. If A actually calls that new method internally, "bad things"tm will almost certainly happen, since B never intended to effectively override the newly-added method in A. This is a very hard problem to isolate yet can be easily remedied by the compiler. The request was first made two or three years back, and once or twice since then: you make the "override" keyword *required*. When "override" is required, the compiler can easily trap this related type of hijacking and avoid such nasty surprises. Walter Bright wrote:I want to continue a bit in the Overloading/Inheritance thread which is getting a little long, on a closely related issue which I find to be important, but so rarely referred to that I had to come up with a name for it - hijacking. Hijacking is when code A depends on B, and then when seemingly unrelated code C is modified, then A's behavior silently changes. Here's an example from C++: --A.h-- void foo(long i); --B.c-- #include "A.h" #include "C.h" .... foo(3); // calls A's foo(long) -------- Let's say A.h and C.h are developed by different people. In C.h, the developer adds: --C.h-- void foo(int i); ----- This does something completely different from A.h's foo(long), because they just happened to share the same name. Now, when B.c is recompiled, it's call to foo is silently *hijacked* by C.h's foo. Because of C++'s overloading rules and lack of modularity, there's no way to programmatically defend against this. Instead, one has to rely on coding conventions (such as using a unique package prefix name on all symbols, like A_foo() and C_foo()). So how does this relate to the overloading/inheritance issues? Consider: ----A.d---- class A { ... } -----B.d---- import A; class B : A { void foo(long); } .... void bar(B b) { b.foo(3); // calls B.foo(long) } ---- Let's say A.d comes from some third party library. Now the developer of A decides to add some functionality to class A, and adds the member function foo(int): ----A.d--- class A { void foo(int); } ------------ Now our hapless B programmer has his calls to B.foo(long) silently hijacked to A.foo(int) (under Java rules). I don't see any reasonable way for B to defend against this. Certainly, developer A doesn't have any idea who is deriving from A (and that's the point of polymorphism) - but should he be disallowed from adding *any* method names? And the hapless B developer, he wrote class B years ago and no longer quite remembers how it works, he just recompiles it and now it silently fails. So, this is one case where I feel C++ got it right, and Java didn't. (P.S. It's not a compiler implementation issue, nor is it a runtime performance issue.)
Aug 05 2007
kris wrote:There's a related problem where a public method is added to a base-class A (as in your example) but where the signature is *exactly* that of one existing in derived class B. If A actually calls that new method internally, "bad things"tm will almost certainly happen, since B never intended to effectively override the newly-added method in A. This is a very hard problem to isolate yet can be easily remedied by the compiler. The request was first made two or three years back, and once or twice since then: you make the "override" keyword *required*. When "override" is required, the compiler can easily trap this related type of hijacking and avoid such nasty surprises.That is a good point. The reason I haven't added it is because I'm not sure how annoying it will be to have to always add the 'override' keyword. It might be one of those things like exception specifications where everyone says it's a good idea but guiltily hate in secret <g>. Mitigating factors are private and final methods cannot be overridden.
Aug 05 2007
Walter Bright Wrote: [re:making 'override' mandatory]That is a good point. The reason I haven't added it is because I'm not sure how annoying it will be to have to always add the 'override' keyword. It might be one of those things like exception specifications where everyone says it's a good idea but guiltily hate in secret <g>.annoyance in the general case; in fact it normally _saves_ typing since you can just type "override" and ReSharper (a refactoring plugin for VS) offers completions based on virtuals in the base class. And it's been a useful warning of unintended overrides many a time. The one case where the rule does feel annoying is when you have an interface, an abstract base class implementing that interface with pure virtuals while providing common functionality, and a concrete subclass. In D you'd probably mixin the base stuff, so this case wouldn't arise.
Aug 05 2007
"Walter Bright" <newshound1 digitalmars.com> wrote in message news:f95leh$hn4$1 digitalmars.com...That is a good point. The reason I haven't added it is because I'm not sure how annoying it will be to have to always add the 'override' keyword. It might be one of those things like exception specifications where everyone says it's a good idea but guiltily hate in secret <g>.If anything's annoying, it's when that kind of hijacking happens (I've had it bite me a few times). I _always_ try to put override on every method that I override, as not only is it self-documenting, but it also traps this kind of bug.
Aug 05 2007
Walter Bright wrote:kris wrote:Let's put it this way: I have a personal and quite open dislike for exception specifications, yet I try very hard to ensure override is added in all the right places in D, even though the compiler doesn't enforce it. In other words, I go to the trouble of adding override for the benefit of manual auditing. The compiler ought to be helping me with that task? - KrisThere's a related problem where a public method is added to a base-class A (as in your example) but where the signature is *exactly* that of one existing in derived class B. If A actually calls that new method internally, "bad things"tm will almost certainly happen, since B never intended to effectively override the newly-added method in A. This is a very hard problem to isolate yet can be easily remedied by the compiler. The request was first made two or three years back, and once or twice since then: you make the "override" keyword *required*. When "override" is required, the compiler can easily trap this related type of hijacking and avoid such nasty surprises.That is a good point. The reason I haven't added it is because I'm not sure how annoying it will be to have to always add the 'override' keyword. It might be one of those things like exception specifications where everyone says it's a good idea but guiltily hate in secret <g>.
Aug 06 2007
kris wrote:In other words, I go to the trouble of adding override for the benefit of manual auditing. The compiler ought to be helping me with that task?I'll put it in as a warning in the next update, and we can try it out.
Aug 06 2007
On Mon, 06 Aug 2007 03:11:14 +0400, Walter Bright <newshound1 digitalmars.com> wrote:kris wrote:Eiffel has same feature for more than 20 years and it really works :) Each method which derived class wants to redefine must be declared in special section: class BASE feature a is ... end b is ... end c is ... end end class DERIVED inherit BASE redefine a, b end feature a is ... end b is ... end end It is error if 'c' is defined in DERIVED without specifying in 'redefine' section. In addition, Scala requires to use 'override' keyword and it also works fine. -- Regards, Yauheni AkhotnikauThere's a related problem where a public method is added to a base-class A (as in your example) but where the signature is *exactly* that of one existing in derived class B. If A actually calls that new method internally, "bad things"tm will almost certainly happen, since B never intended to effectively override the newly-added method in A. This is a very hard problem to isolate yet can be easily remedied by the compiler. The request was first made two or three years back, and once or twice since then: you make the "override" keyword *required*. When "override" is required, the compiler can easily trap this related type of hijacking and avoid such nasty surprises.That is a good point. The reason I haven't added it is because I'm not sure how annoying it will be to have to always add the 'override' keyword. It might be one of those things like exception specifications where everyone says it's a good idea but guiltily hate in secret <g>.
Aug 06 2007
eao197 wrote:Eiffel has same feature for more than 20 years and it really works :)Eiffel has many good ideas, but we must be careful thinking of Eiffel as an endorsement, as it failed to catch on. I think one reason it failed is because of the syntax.
Aug 06 2007
On Mon, 06 Aug 2007 21:30:43 +0400, Walter Bright = <newshound1 digitalmars.com> wrote:eao197 wrote:Eiffel has same feature for more than 20 years and it really works :)=Eiffel has many good ideas, but we must be careful thinking of Eiffel =as =an endorsement, as it failed to catch on. I think one reason it failed==is because of the syntax.No, I don't think so. I spent last 1.5 month to study Eiffel. Eiffel = syntax isn't a problem (moreover I think Eiffel/Ruby syntax is more = attractive than old C curly braces tradition). By main opinion the main Eiffel's problems are: 1. Only one paradim. Only OOP and only by following the Eiffel method. 2. Comand/query separation principle. For example, you can't do somethin= g = with object and get the result, as in C++/D: auto sent_result =3D mail_box.send_message(msg); In Eiffel send_message must be command, and mail_box must have a query t= o = retrive last send result: local send_result: SEND_RESULT do mail_box.send_message (msg) send_result :=3D mail_box.last_send_result ... end 3. Very different exception mechanism. For example see my question about= = resouce cleanup in the case of exception: = http://tech.groups.yahoo.com/group/eiffel_software/message/11062 But 'DesignByContract' and inheritance (and various forms of inheritance= = conflicts resolving) are really great part of Eiffel. So I vote for mandatory 'override' keyword in D too. -- = Regards, Yauheni Akhotnikau
Aug 06 2007
Walter Bright wrote:eao197 wrote:My suspicion of the reason that Eiffel failed to catch on is the personality and resultant policies of the designer. It took a long time for SmallEiffel to be released...and it's policies aren't that friendly, either, even though it IS GPL software. OTOH, IMNSHO, Eiffel did make a few serious mistakes. One of them was in forbidding two different functions (essentially the same) to be distinguished by their argument list, but not by their name. BAD decision. So you're right when you say "be careful", but don't attribute most of the failure of Eiffel to it's design. Other factors predominated. Note that D already had three branches DMD1, DMD2, and gdc. And that they share a lot of the same code (which keeps duplicate effort to a minimum). If you want to copy organization policies, copy from Python, but Eiffel had very many good ideas that a compiler language could benefit from. (I'm not as convinced by modern versions of Eiffel as I was by the earlier ones...but then I've basically stopped following it, because it kept breaking all of it's libraries with each new release. And it never did become as easy to link to C as D already is. [Now if only there was a decent way to manage C++ linkage.])Eiffel has same feature for more than 20 years and it really works :)Eiffel has many good ideas, but we must be careful thinking of Eiffel as an endorsement, as it failed to catch on. I think one reason it failed is because of the syntax.
Aug 06 2007
Charles D Hixson wrote:So you're right when you say "be careful", but don't attribute most of the failure of Eiffel to it's design. Other factors predominated.For a complex thing like a language, it can be really hard to pin down why it failed. Ask n different people, and you'll get n different answers. What turned me off was the syntax. It just means we have to be extra careful about adopting features from a failed language. The further a feature is from mainstream convention in at least one successful language, the more nervous I get about it.
Aug 06 2007
Walter Bright wrote:kris wrote:My vote was, and still is, for 'override' to be mandatory. ReganThere's a related problem where a public method is added to a base-class A (as in your example) but where the signature is *exactly* that of one existing in derived class B. If A actually calls that new method internally, "bad things"tm will almost certainly happen, since B never intended to effectively override the newly-added method in A. This is a very hard problem to isolate yet can be easily remedied by the compiler. The request was first made two or three years back, and once or twice since then: you make the "override" keyword *required*. When "override" is required, the compiler can easily trap this related type of hijacking and avoid such nasty surprises.That is a good point. The reason I haven't added it is because I'm not sure how annoying it will be to have to always add the 'override' keyword. It might be one of those things like exception specifications where everyone says it's a good idea but guiltily hate in secret <g>. Mitigating factors are private and final methods cannot be overridden.
Aug 06 2007
Regan Heath wrote:Walter Bright wrote:Me too. Note that since you can use 'override { }' or 'override:', it's less onerous than putting 'virtual' in front of every function in C++.kris wrote:My vote was, and still is, for 'override' to be mandatory. ReganThere's a related problem where a public method is added to a base-class A (as in your example) but where the signature is *exactly* that of one existing in derived class B. If A actually calls that new method internally, "bad things"tm will almost certainly happen, since B never intended to effectively override the newly-added method in A. This is a very hard problem to isolate yet can be easily remedied by the compiler. The request was first made two or three years back, and once or twice since then: you make the "override" keyword *required*. When "override" is required, the compiler can easily trap this related type of hijacking and avoid such nasty surprises.That is a good point. The reason I haven't added it is because I'm not sure how annoying it will be to have to always add the 'override' keyword. It might be one of those things like exception specifications where everyone says it's a good idea but guiltily hate in secret <g>. Mitigating factors are private and final methods cannot be overridden.
Aug 06 2007
Don Clugston wrote:Me too. Note that since you can use 'override { }' or 'override:', it's less onerous than putting 'virtual' in front of every function in C++.How does "override:" work with other properties used as labels? Is it disabled when public/protected/private is next used in the same way? Sean
Aug 06 2007
Sean Kelly wrote:How does "override:" work with other properties used as labels? Is it disabled when public/protected/private is next used in the same way?It adds to them.
Aug 06 2007
Walter Bright wrote:Sean Kelly wrote:So is there anyway to disable "override:" once set? SeanHow does "override:" work with other properties used as labels? Is it disabled when public/protected/private is next used in the same way?It adds to them.
Aug 06 2007
Sean Kelly wrote:Walter Bright wrote:Since there is no "not an override" keyword, I would wager there isn't. (Unless for end of current scope, aye? But even then...) I don't think we really need a non-override keyword, and I wouldn't want 'final' to be given that effect either ('final override' should be a valid attribute), or any other existing attributes... so our options are: attribute. Maybe '!foo:' or similar. -- Chris Nicholson-SaulsSean Kelly wrote:So is there anyway to disable "override:" once set? SeanHow does "override:" work with other properties used as labels? Is it disabled when public/protected/private is next used in the same way?It adds to them.
Aug 06 2007
Chris Nicholson-Sauls wrote:Same here. Using "override:" doesn't seem feasible in all but the simplest cases. Sean
Aug 06 2007
Chris Nicholson-Sauls wrote: > I don't think we really need a non-override keyword, and I wouldn't want'final' to be given that effect either ('final override' should be a valid attribute), or any other existing attributes... so our options are: attribute. Maybe '!foo:' or similar. -- Chris Nicholson-Saulsoverride: void foo() {} void bar() {} default: void baz() {} But then again, maybe in this case we should just use override {} or reorder methods.
Aug 07 2007
Sean Kelly wrote:Walter Bright wrote:No.Sean Kelly wrote:So is there anyway to disable "override:" once set?How does "override:" work with other properties used as labels? Is it disabled when public/protected/private is next used in the same way?It adds to them.
Aug 06 2007
Regan Heath schrieb:My vote was, and still is, for 'override' to be mandatory. ReganAs said in my posting http://www.digitalmars.com/d/archives/digitalmars/D/aliasing_base_methods_49572.html#N49577 , i still second that also.
Aug 06 2007
Frank Benoit Wrote:Regan Heath schrieb:votes++; It's really not that hard and will catch a lot of errors. Plus, a good IDE can insert that stuff automatically.My vote was, and still is, for 'override' to be mandatory. ReganAs said in my posting http://www.digitalmars.com/d/archives/digitalmars/D/aliasing_base_methods_49572.html#N49577 , i still second that also.
Aug 06 2007
Walter Bright wrote:keyword. It might be one of those things like exception specifications where everyone says it's a good idea but guiltily hate in secret <g>.I don't think the mainstream opinion in Java is that checked exceptions are a good ideia. -- Bruno Medeiros - MSc in CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Aug 06 2007
Bruno Medeiros wrote:Walter Bright wrote:It's not a great analogy, because there are very good technical arguments against checked exceptions. But I do remember prominent Java people promoting checked exceptions as a great idea, while in their own code they'd subvert them because they were just too annoying. I also think that mainstream Java has evolved its understanding of checked exceptions.keyword. It might be one of those things like exception specifications where everyone says it's a good idea but guiltily hate in secret <g>.I don't think the mainstream opinion in Java is that checked exceptions are a good ideia.
Aug 06 2007
"Walter Bright" <newshound1 digitalmars.com> kirjoitti viestissä news:f95leh$hn4$1 digitalmars.com...It might be one of those things like exception specifications where everyone says it's a good idea but guiltily hate in secret <g>.Exception specification *is* a good idea. Although I do hate it - try to remember what a specific method may throw when you write your code, especially if the error is ambiguous like "Unhandled exception" it's really irritating - but I hate unspecified exceptions even more, as the problem then is to even remember to put in the necessary try-catch-finally blocks.
Aug 06 2007
"Rioshin an'Harthen" <rharth75 hotmail.com> wrote in message news:f974u9$9k1$1 digitalmars.com..."Walter Bright" <newshound1 digitalmars.com> kirjoitti viestissä news:f95leh$hn4$1 digitalmars.com...Not to start a big big debate on it, but my own personal feeling on that (after having used a fair amount of it) is that the specification of exceptions belongs in generated documentation (whether javadoc-style or as part of the IDE as with "some_function() -> Called By..."). I normally prefer having to explicity specify things (yea, strong-typing fan here ;) ), but personally, I find it overkill in this case. (Not to mention it gave me flashbacks of writing C/C++ headers. j/k ;) ).It might be one of those things like exception specifications where everyone says it's a good idea but guiltily hate in secret <g>.Exception specification *is* a good idea. Although I do hate it - try to remember what a specific method may throw when you write your code, especially if the error is ambiguous like "Unhandled exception" it's really irritating - but I hate unspecified exceptions even more, as the problem then is to even remember to put in the necessary try-catch-finally blocks.
Aug 06 2007
Nick Sabalausky wrote:"Rioshin an'Harthen" <rharth75 hotmail.com> wrote in message news:f974u9$9k1$1 digitalmars.com...I didn't mind it at first, in that the Java compiler would then let me know if I'd missed any potential exceptions... ...but when I noticed I was just adding 'throws A,B,C' to a lot of my methods, I decided it wasn't entirely a great thing afterall. What would have been better, I think, would have been to make throws specifications /optional/. A thing libraries should do, but which applications should be allowed to quietly "forget" most of the time. Java is the language of conventions, after all. -- Chris Nicholson-Sauls"Walter Bright" <newshound1 digitalmars.com> kirjoitti viestissä news:f95leh$hn4$1 digitalmars.com...Not to start a big big debate on it, but my own personal feeling on that (after having used a fair amount of it) is that the specification of exceptions belongs in generated documentation (whether javadoc-style or as part of the IDE as with "some_function() -> Called By..."). I normally prefer having to explicity specify things (yea, strong-typing fan here ;) ), but personally, I find it overkill in this case. (Not to mention it gave me flashbacks of writing C/C++ headers. j/k ;) ).It might be one of those things like exception specifications where everyone says it's a good idea but guiltily hate in secret <g>.Exception specification *is* a good idea. Although I do hate it - try to remember what a specific method may throw when you write your code, especially if the error is ambiguous like "Unhandled exception" it's really irritating - but I hate unspecified exceptions even more, as the problem then is to even remember to put in the necessary try-catch-finally blocks.
Aug 06 2007
Chris Nicholson-Sauls Wrote:Nick Sabalausky wrote:I'd like it to be required in the method where the exception is thrown for checked exceptions, but not in any calling methods (they're just optional there). But I'm not too passionate about the point... I can live with 'em (they're a bit annoying, but I can see their advantages), and I can live without 'em."Rioshin an'Harthen" <rharth75 hotmail.com> wrote in message news:f974u9$9k1$1 digitalmars.com...I didn't mind it at first, in that the Java compiler would then let me know if I'd missed any potential exceptions... ...but when I noticed I was just adding 'throws A,B,C' to a lot of my methods, I decided it wasn't entirely a great thing afterall. What would have been better, I think, would have been to make throws specifications /optional/. A thing libraries should do, but which applications should be allowed to quietly "forget" most of the time. Java is the language of conventions, after all. -- Chris Nicholson-Sauls"Walter Bright" <newshound1 digitalmars.com> kirjoitti viestissä news:f95leh$hn4$1 digitalmars.com...Not to start a big big debate on it, but my own personal feeling on that (after having used a fair amount of it) is that the specification of exceptions belongs in generated documentation (whether javadoc-style or as part of the IDE as with "some_function() -> Called By..."). I normally prefer having to explicity specify things (yea, strong-typing fan here ;) ), but personally, I find it overkill in this case. (Not to mention it gave me flashbacks of writing C/C++ headers. j/k ;) ).It might be one of those things like exception specifications where everyone says it's a good idea but guiltily hate in secret <g>.Exception specification *is* a good idea. Although I do hate it - try to remember what a specific method may throw when you write your code, especially if the error is ambiguous like "Unhandled exception" it's really irritating - but I hate unspecified exceptions even more, as the problem then is to even remember to put in the necessary try-catch-finally blocks.
Aug 06 2007
Nick Sabalausky wrote:"Rioshin an'Harthen" <rharth75 hotmail.com> wrote in message news:f974u9$9k1$1 digitalmars.com...I agree with this 100%. With check exceptions it just becomes too annoying and verbose. Without them, often it is too difficult to find out what exceptions are possible for a function to throw. So the right place seems to be an analysis / doc-generation tool / IDE. --bb"Walter Bright" <newshound1 digitalmars.com> kirjoitti viestissä news:f95leh$hn4$1 digitalmars.com...Not to start a big big debate on it, but my own personal feeling on that (after having used a fair amount of it) is that the specification of exceptions belongs in generated documentation (whether javadoc-style or as part of the IDE as with "some_function() -> Called By..."). I normally prefer having to explicity specify things (yea, strong-typing fan here ;) ), but personally, I find it overkill in this case. (Not to mention it gave me flashbacks of writing C/C++ headers. j/k ;) ).It might be one of those things like exception specifications where everyone says it's a good idea but guiltily hate in secret <g>.Exception specification *is* a good idea. Although I do hate it - try to remember what a specific method may throw when you write your code, especially if the error is ambiguous like "Unhandled exception" it's really irritating - but I hate unspecified exceptions even more, as the problem then is to even remember to put in the necessary try-catch-finally blocks.
Aug 07 2007
Bill Baxter wrote:Nick Sabalausky wrote:Interesting thing I'd like to mention, again about how IDEs affect the language design and influence it's advantages and disadvantages. I too find checked exceptions annoying, but this is an example of a language disadvantage has been practically nullified by the IDE (JDT). First I took a slightly modified ExceptionAdapter class such as the one from Bruce Eckel's article: http://www.mindview.net/Etc/Discussions/CheckedExceptions (basicly ExceptionAdapter is class that wraps a checked exception in an unchecked exception, allowing it to be thrown unchecked) So when you have something like this: foo.doSomething(); // throws a normal exception and Java will complain that an exception is thrown, you add this: try { foo.doSomething(); // throws a normal exception } catch(FooException fe) { ExceptionAdapter.unchecked(fe); } and there is no longer a compiler error (unchecked is a static method that wraps the exception), without having needed to put throws clauses in all method along the call hierarchy. This is an interesting workaround, but it is still annoying to have to write that try-catch code whenever an exception is thrown. The second part is where JDT comes in. Whenever you have this: foo.doSomething(); // throws a normal exception the IDE compiler will show and highlight the error, and then you can press Ctrl+1 on the error (Quick-Assist), showing a list of possible fixes, one of them being "Surround with Try-Catch". If you select it, JDT will automatically add the try-catch code, like this: try { foo.doSomething(); // throws a normal exception } catch(FooException fe) { // TODO: catch exception here } Note that the catch clause is automatically set to the thrown exception. But furthermore you can change the template of code that is created with this try-catch quick-fix, so that instead of the "// TODO:" line, you put the "ExceptionAdapter.unchecked(...);" line. So now whenever this quick fix is invoked, it will automatically generate all necessary code, and you're now able to avoid the checked exception problem with just a few keystrokes (Ctrl+1, Down, Enter). :) As an added bonus, if some time you feel the need to rigorously specify your code, you can then search for calls of the ExceptionAdapter.unchecked method, to find points where you can turn unchecked exceptions into checked ones. -- Bruno Medeiros - MSc in CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D"Rioshin an'Harthen" <rharth75 hotmail.com> wrote in message news:f974u9$9k1$1 digitalmars.com...I agree with this 100%. With check exceptions it just becomes too annoying and verbose. Without them, often it is too difficult to find out what exceptions are possible for a function to throw. So the right place seems to be an analysis / doc-generation tool / IDE. --bb"Walter Bright" <newshound1 digitalmars.com> kirjoitti viestissä news:f95leh$hn4$1 digitalmars.com...Not to start a big big debate on it, but my own personal feeling on that (after having used a fair amount of it) is that the specification of exceptions belongs in generated documentation (whether javadoc-style or as part of the IDE as with "some_function() -> Called By..."). I normally prefer having to explicity specify things (yea, strong-typing fan here ;) ), but personally, I find it overkill in this case. (Not to mention it gave me flashbacks of writing C/C++ headers. j/k ;) ).It might be one of those things like exception specifications where everyone says it's a good idea but guiltily hate in secret <g>.Exception specification *is* a good idea. Although I do hate it - try to remember what a specific method may throw when you write your code, especially if the error is ambiguous like "Unhandled exception" it's really irritating - but I hate unspecified exceptions even more, as the problem then is to even remember to put in the necessary try-catch-finally blocks.
Aug 08 2007
On Wed, 08 Aug 2007 15:38:14 +0400, Bruno Medeiros <brunodomedeiros+spam com.gmail> wrote:Bill Baxter wrote:I don't agree (almost complitely). Checked expession is not simply annoying. Sometimes they lead to bad-style and erroneous code. For example imagine you redefine some method: class MySpecializedClass extends SomeGeneralClass { public void someMethod() throws DomainSpecificException { ... } } but you need to use temporary file in someMethod() implementation (or need to run some external tool, or need to use some crypto library). And File.createTempFile throws IllegalArgumentException or IOException or SecurityException, but no one of them is in someMethod 'throws' clause. In such case you have only two possibilities: wrap the exception which is thrown by File.createTempFile into some another exception (it is good if DomainSpecificException allows that, but in an usual case it don't) or catch and hide the original exception. As I seen in the past many developers prefered catch and hide exception. And this is not a good approach I think. So in my opinion it is better to write code which doesn't depend on particular kind of exception. Assumption that any part of code could throws any kind of exception lead to more reliable software (Erlang is an evidence). The exception safety in much more hard in C++ where there is manual memory management and there isn't scope()-constructs like in D. So I hope that writting exception safe code in D is much more easy, than in C++ or in Java with checked exceptions. However sometimes is good to know that some method doesn't throw exception at all (it could be necessary for exception safety, like C++ convection that swap() methods and destructors are exception free). So I suppose to introduce 'nothrows' modifier as a sign that some routine is exception free: bool is_item_in_array( int[] array, int item ) nothrows { ... } Compiler could checks nothrows-routines. It is an error if nothrows-routine calls any routine without 'nothrows' modifier. So it could be an crear advice to programmer: if it has some data which must be protected from exception and he calls any routine without 'nothrows' modifier he must do some action to protect his data. -- Regards, Yauheni AkhotnikauNick Sabalausky wrote:Interesting thing I'd like to mention, again about how IDEs affect the language design and influence it's advantages and disadvantages. I too find checked exceptions annoying, but this is an example of a language disadvantage has been practically nullified by the IDE (JDT). First I took a slightly modified ExceptionAdapter class such as the one from Bruce Eckel's article: http://www.mindview.net/Etc/Discussions/CheckedExceptions (basicly ExceptionAdapter is class that wraps a checked exception in an unchecked exception, allowing it to be thrown unchecked) So when you have something like this: foo.doSomething(); // throws a normal exception and Java will complain that an exception is thrown, you add this: try { foo.doSomething(); // throws a normal exception } catch(FooException fe) { ExceptionAdapter.unchecked(fe); } and there is no longer a compiler error (unchecked is a static method that wraps the exception), without having needed to put throws clauses in all method along the call hierarchy. This is an interesting workaround, but it is still annoying to have to write that try-catch code whenever an exception is thrown. The second part is where JDT comes in. Whenever you have this: foo.doSomething(); // throws a normal exception the IDE compiler will show and highlight the error, and then you can press Ctrl+1 on the error (Quick-Assist), showing a list of possible fixes, one of them being "Surround with Try-Catch". If you select it, JDT will automatically add the try-catch code, like this: try { foo.doSomething(); // throws a normal exception } catch(FooException fe) { // TODO: catch exception here } Note that the catch clause is automatically set to the thrown exception. But furthermore you can change the template of code that is created with this try-catch quick-fix, so that instead of the "// TODO:" line, you put the "ExceptionAdapter.unchecked(...);" line. So now whenever this quick fix is invoked, it will automatically generate all necessary code, and you're now able to avoid the checked exception problem with just a few keystrokes (Ctrl+1, Down, Enter). :) As an added bonus, if some time you feel the need to rigorously specify your code, you can then search for calls of the ExceptionAdapter.unchecked method, to find points where you can turn unchecked exceptions into checked ones."Rioshin an'Harthen" <rharth75 hotmail.com> wrote in message news:f974u9$9k1$1 digitalmars.com...I agree with this 100%. With check exceptions it just becomes too annoying and verbose. Without them, often it is too difficult to find out what exceptions are possible for a function to throw. So the right place seems to be an analysis / doc-generation tool / IDE. --bb"Walter Bright" <newshound1 digitalmars.com> kirjoitti viestissä news:f95leh$hn4$1 digitalmars.com...Not to start a big big debate on it, but my own personal feeling on that (after having used a fair amount of it) is that the specification of exceptions belongs in generated documentation (whether javadoc-style or as part of the IDE as with "some_function() -> Called By..."). I normally prefer having to explicity specify things (yea, strong-typing fan here ;) ), but personally, I find it overkill in this case. (Not to mention it gave me flashbacks of writing C/C++ headers. j/k ;) ).It might be one of those things like exception specifications where everyone says it's a good idea but guiltily hate in secret <g>.Exception specification *is* a good idea. Although I do hate it - try to remember what a specific method may throw when you write your code, especially if the error is ambiguous like "Unhandled exception" it's really irritating - but I hate unspecified exceptions even more, as the problem then is to even remember to put in the necessary try-catch-finally blocks.
Aug 08 2007
On Wed, 08 Aug 2007 17:05:07 +0400, eao197 <eao197 intervale.ru> wrote:So in my opinion it is better to write code which doesn't depend on =particular kind of exception. Assumption that any part of code could =throws any kind of exception lead to more reliable software (Erlang is==an evidence). The exception safety in much more hard in C++ where there is manual =memory management and there isn't scope()-constructs like in D. So I =hope that writting exception safe code in D is much more easy, than in==C++ or in Java with checked exceptions. However sometimes is good to know that some method doesn't throw =exception at all (it could be necessary for exception safety, like =C++ convection that swap() methods and destructors are exception free)=. =So I suppose to introduce 'nothrows' modifier as a sign that some =routine is exception free: bool is_item_in_array( int[] array, int item ) nothrows { ... } Compiler could checks nothrows-routines. It is an error if =nothrows-routine calls any routine without 'nothrows' modifier. So it could be an crear advice to programmer: if it has some data whic=h =must be protected from exception and he calls any routine without ='nothrows' modifier he must do some action to protect his data.Yet more ideas about 'nothrows' modifier (sorry for wasting your time). Which routines need 'nothrows' specifications? Obvious (for me) answer is: various forms of cleanup-routines. For = example: File.close, Mutex.release, DbConnection.disconnect and so on. = E.g. routines which will be used in destructors, scope-constructs and = finally-blocks. So, compiler could checks all calls in those constructs = = and reports warning (or even errors) if any method without 'nothrows' is= = being called. Even more. In some situation cleanup actions could be performed in = catch-blocks. To ensure that no exception will be thrown during cleanup = = programmer could write: nothrows { ... // some actions... } and compiler will check all calls in such block. For example: // Create new DB connection for user. // And checks user right. If user has no right (has expiried password) t= hen // exception is thrown. UserSession open_user_section( string user_name, string user_password ) { auto db_connection =3D establish_db_connection(); try { check_user_rights( db_connection, user_name, user_password ); ... // Some other actions... } catch( Exception x ) { nothrows { cleanup_db_connection( db_connection ); ... // Some other cleanup actions... } log_session_creation_error( x ); throw; } return new UserSession( db_connection, user_name ); } So compiler could check that no exception is allowed in cleanup actions.= = But new exception could be thrown in 'log_session_creation_error' method= . -- = Regards, Yauheni Akhotnikau
Aug 08 2007
eao197 wrote:However sometimes is good to know that some method doesn't throw exception at all (it could be necessary for exception safety, like C++ convection that swap() methods and destructors are exception free). So I suppose to introduce 'nothrows' modifier as a sign that some routine is exception free:The compiler can support this. It'd have to add more metadata to precompiled libraries, but that's okay. The ddocs could then (optionally?) include information on what exceptions the function throws directly and what other exceptions can be thrown on invocation. So I don't see any reason for the programmer to have to manually do all this. -cbw
Aug 09 2007
On Fri, 10 Aug 2007 06:03:10 +0400, Christopher Wright = <dhasenan gmail.com> wrote:eao197 wrote:However sometimes is good to know that some method doesn't throw =+ =exception at all (it could be necessary for exception safety, like C+=o =convection that swap() methods and destructors are exception free). S=e =I suppose to introduce 'nothrows' modifier as a sign that some routin=is exception free:The compiler can support this. It'd have to add more metadata to =precompiled libraries, but that's okay. The ddocs could then =(optionally?) include information on what exceptions the function thro=ws =directly and what other exceptions can be thrown on invocation. So I don't see any reason for the programmer to have to manually do al=l =this.There are one important use case where the compiler can't detect which = exceptions are thrown by a method: polymorphism and late binding. Imagin= e: class EventHandler { abstract void handle_input(); abstract void handle_output(); abstract void handle_exception(); ... } class SelectReactor : Reactor { void reactor_event_loop() { while( true ) { EventHandler[] input_ready_handlers =3D = detect_input_ready_handlers(); foreach( h; input_ready_handlers ) h.handle_input(); ... } } } During compilation of SelectReactor the compiler can't determine which = exception could be thrown by descendants of EventHandler. So it is a = programmer's task to specify exceptions in 'throws' clause (like in = 'nothrows' clause (like throw() in C++). -- = Regards, Yauheni Akhotnikau
Aug 09 2007
eao197 wrote:On Wed, 08 Aug 2007 15:38:14 +0400, Bruno Medeiros <brunodomedeiros+spam com.gmail> wrote:I don't see how that is disagreeing with what I said before. Note that the above doesn't hide the exception (as in, make it disappear), it gets re-thrown as an unchecked exception. -- Bruno Medeiros - MSc in CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#DBill Baxter wrote:I don't agree (almost complitely). Checked expession is not simply annoying. Sometimes they lead to bad-style and erroneous code. For example imagine you redefine some method: class MySpecializedClass extends SomeGeneralClass { public void someMethod() throws DomainSpecificException { ... } } but you need to use temporary file in someMethod() implementation (or need to run some external tool, or need to use some crypto library). And File.createTempFile throws IllegalArgumentException or IOException or SecurityException, but no one of them is in someMethod 'throws' clause. In such case you have only two possibilities: wrap the exception which is thrown by File.createTempFile into some another exception (it is good if DomainSpecificException allows that, but in an usual case it don't) or catch and hide the original exception. As I seen in the past many developers prefered catch and hide exception. And this is not a good approach I think. So in my opinion it is better to write code which doesn't depend on particular kind of exception. Assumption that any part of code could throws any kind of exception lead to more reliable software (Erlang is an evidence).Nick Sabalausky wrote:Interesting thing I'd like to mention, again about how IDEs affect the language design and influence it's advantages and disadvantages. I too find checked exceptions annoying, but this is an example of a language disadvantage has been practically nullified by the IDE (JDT). First I took a slightly modified ExceptionAdapter class such as the one from Bruce Eckel's article: http://www.mindview.net/Etc/Discussions/CheckedExceptions (basicly ExceptionAdapter is class that wraps a checked exception in an unchecked exception, allowing it to be thrown unchecked) So when you have something like this: foo.doSomething(); // throws a normal exception and Java will complain that an exception is thrown, you add this: try { foo.doSomething(); // throws a normal exception } catch(FooException fe) { ExceptionAdapter.unchecked(fe); } and there is no longer a compiler error (unchecked is a static method that wraps the exception), without having needed to put throws clauses in all method along the call hierarchy. This is an interesting workaround, but it is still annoying to have to write that try-catch code whenever an exception is thrown. The second part is where JDT comes in. Whenever you have this: foo.doSomething(); // throws a normal exception the IDE compiler will show and highlight the error, and then you can press Ctrl+1 on the error (Quick-Assist), showing a list of possible fixes, one of them being "Surround with Try-Catch". If you select it, JDT will automatically add the try-catch code, like this: try { foo.doSomething(); // throws a normal exception } catch(FooException fe) { // TODO: catch exception here } Note that the catch clause is automatically set to the thrown exception. But furthermore you can change the template of code that is created with this try-catch quick-fix, so that instead of the "// TODO:" line, you put the "ExceptionAdapter.unchecked(...);" line. So now whenever this quick fix is invoked, it will automatically generate all necessary code, and you're now able to avoid the checked exception problem with just a few keystrokes (Ctrl+1, Down, Enter). :) As an added bonus, if some time you feel the need to rigorously specify your code, you can then search for calls of the ExceptionAdapter.unchecked method, to find points where you can turn unchecked exceptions into checked ones."Rioshin an'Harthen" <rharth75 hotmail.com> wrote in message news:f974u9$9k1$1 digitalmars.com...I agree with this 100%. With check exceptions it just becomes too annoying and verbose. Without them, often it is too difficult to find out what exceptions are possible for a function to throw. So the right place seems to be an analysis / doc-generation tool / IDE. --bb"Walter Bright" <newshound1 digitalmars.com> kirjoitti viestissä news:f95leh$hn4$1 digitalmars.com...Not to start a big big debate on it, but my own personal feeling on that (after having used a fair amount of it) is that the specification of exceptions belongs in generated documentation (whether javadoc-style or as part of the IDE as with "some_function() -> Called By..."). I normally prefer having to explicity specify things (yea, strong-typing fan here ;) ), but personally, I find it overkill in this case. (Not to mention it gave me flashbacks of writing C/C++ headers. j/k ;) ).It might be one of those things like exception specifications where everyone says it's a good idea but guiltily hate in secret <g>.Exception specification *is* a good idea. Although I do hate it - try to remember what a specific method may throw when you write your code, especially if the error is ambiguous like "Unhandled exception" it's really irritating - but I hate unspecified exceptions even more, as the problem then is to even remember to put in the necessary try-catch-finally blocks.
Aug 10 2007
On Fri, 10 Aug 2007 14:15:47 +0400, Bruno Medeiros <brunodomedeiros+spam com.gmail> wrote:I don't see how that is disagreeing with what I said before. Note that the above doesn't hide the exception (as in, make it disappear), it gets re-thrown as an unchecked exception.Umm... I'm sorry, I thought that 'ExceptionAdapter.unchecked(fe)' simply hides exception. But initaly I was disagree with that:Easy method of incapsulating exception into unchecked one doesn't repair flaw in the language design. -- Regards, Yauheni Akhotnikauan example of a language disadvantage has been practically nullified by the IDE (JDT).
Aug 10 2007
eao197 wrote:On Fri, 10 Aug 2007 14:15:47 +0400, Bruno Medeiros <brunodomedeiros+spam com.gmail> wrote:No, it doesn't do that. And indeed it would be bad if it did.I don't see how that is disagreeing with what I said before. Note that the above doesn't hide the exception (as in, make it disappear), it gets re-thrown as an unchecked exception.Umm... I'm sorry, I thought that 'ExceptionAdapter.unchecked(fe)' simply hides exception.But initaly I was disagree with that:It fixes it well enough for me. :) -- Bruno Medeiros - MSc in CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#DEasy method of incapsulating exception into unchecked one doesn't repair flaw in the language design.an example of a language disadvantage has been practically nullified by the IDE (JDT).
Aug 10 2007
Walter Bright wrote:That is a good point. The reason I haven't added it is because I'm not sure how annoying it will be to have to always add the 'override' keyword. It might be one of those things like exception specifications where everyone says it's a good idea but guiltily hate in secret <g>.Hmmmm... even I think that requiring the override keyword is okay, and I am not exactly known to be a discipline and bondage fanatic. ^^ Regards, Frank
Aug 06 2007
Reply to Walter,kris wrote:How hard would it be to put a command line flag on the 2.0 version that would turn it on?There's a related problem where a public method is added to a base-class A (as in your example) but where the signature is *exactly* that of one existing in derived class B. If A actually calls that new method internally, "bad things"tm will almost certainly happen, since B never intended to effectively override the newly-added method in A. This is a very hard problem to isolate yet can be easily remedied by the compiler. The request was first made two or three years back, and once or twice since then: you make the "override" keyword *required*. When "override" is required, the compiler can easily trap this related type of hijacking and avoid such nasty surprises.That is a good point. The reason I haven't added it is because I'm not sure how annoying it will be to have to always add the 'override' keyword. It might be one of those things like exception specifications where everyone says it's a good idea but guiltily hate in secret <g>. Mitigating factors are private and final methods cannot be overridden.
Aug 06 2007
BCS wrote:Reply to Walter, How hard would it be to put a command line flag on the 2.0 version that would turn it on?[Compulsory override keyword, I presume] Or rather, one to turn it off? ;-) Regards, Frank
Aug 06 2007
Reply to 0ffh,BCS wrote:eitherReply to Walter, How hard would it be to put a command line flag on the 2.0 version that would turn it on?[Compulsory override keyword, I presume] Or rather, one to turn it off? ;-) Regards, Frank
Aug 06 2007
Walter Bright wrote:kris wrote:Although, I generally like the idea, I fear that requiring 'override' will have side effects for mixins. The writer of the mixin has no way of knowing if the methods will override something or not. I'm thinking the only reasonable solution would be to allow mixins to go on as they currently are, without enforcing the use of 'override'. However, an accidental override that comes in via a mixin seems like a very likely source of subtle bugs. And requiring a special exception to the rules is not really desirable in the first place. --bbThere's a related problem where a public method is added to a base-class A (as in your example) but where the signature is *exactly* that of one existing in derived class B. If A actually calls that new method internally, "bad things"tm will almost certainly happen, since B never intended to effectively override the newly-added method in A. This is a very hard problem to isolate yet can be easily remedied by the compiler. The request was first made two or three years back, and once or twice since then: you make the "override" keyword *required*. When "override" is required, the compiler can easily trap this related type of hijacking and avoid such nasty surprises.That is a good point. The reason I haven't added it is because I'm not sure how annoying it will be to have to always add the 'override' keyword. It might be one of those things like exception specifications where everyone says it's a good idea but guiltily hate in secret <g>. Mitigating factors are private and final methods cannot be overridden.
Aug 07 2007
Bill Baxter wrote:Although, I generally like the idea, I fear that requiring 'override' will have side effects for mixins. The writer of the mixin has no way of knowing if the methods will override something or not.I didn't think of that. But I'll put the check in as a warning, and we'll see if there are real problems or not.
Aug 07 2007
Walter Bright wrote:Bill Baxter wrote:There are probably on two likely scenarios for that: user to a potential (serious) hazard. On the other hand, if the overlap is not an issue, or even on purpose, the workaround is clumsy and kludgy: class B { int foo() {...} } template M { int foo() {...} int bar() {...} } class D : B { mixin M _m; alias _m.bar bar; override int foo () { return _m.foo(); } } Chances are that a relative straightforward CheckOverrides() template or CTF could be used to auto-generate this. There is still, however, the issue of a superfluous proxy method being written, whether by the programmer or by CheckOverrides(). In the first, the situation is an accident. Perhaps D was not previously derived from B, but is now as a result of refactoring, and the unnecessary mixin statement was simply missed. The compiler has caught a programmer error. Good Thing. In the second, perhaps class B had overwritten some of the mixin's methods to behave differently, and class D intends to re-mix the default behavior (perhaps to expose its own changes). In this case perhaps one could wrap the mixin statement and subsequent overwrites in an 'override {...}' block and be good to go. template M { int foo() {...} int bar() {...} } class B { mixin M; int foo() {...custom version...} } class D : B { override { mixin M; int bar() {...custom version...} } } It makes for nice grouping as well, even if it is a workaround. Of course I might have missed some other case where this could happen. -- Chris Nicholson-SaulsAlthough, I generally like the idea, I fear that requiring 'override' will have side effects for mixins. The writer of the mixin has no way of knowing if the methods will override something or not.I didn't think of that. But I'll put the check in as a warning, and we'll see if there are real problems or not.
Aug 07 2007
Bill Baxter wrote:Walter Bright wrote:Interesting point. I think, however, that an explicit solution which re-enables using mixins as overriding functions is the best solution (as you point out, the alternative is subtle bugs). Perhaps a new form of alias, to add the override? template Foo() { int foo() { return x*x; } } class Base { int foo() { return 5; } } class Derived : Base { int x = 5; mixin Foo my_foo; // specify that my_foo.foo overrides Base.foo alias my_foo.foo Base.foo; // or specify that my_foo.foo is an override alias my_foo.foo override foo; // (but obviously not both at once) } -- Reiner PS. Notice how I've (not-so-)subtly worked in my suggestion from http://www.digitalmars.com/d/archives/digitalmars/D/Implementing_required_methods_w th_alias_56011.html ;-)kris wrote:Although, I generally like the idea, I fear that requiring 'override' will have side effects for mixins. The writer of the mixin has no way of knowing if the methods will override something or not. I'm thinking the only reasonable solution would be to allow mixins to go on as they currently are, without enforcing the use of 'override'. However, an accidental override that comes in via a mixin seems like a very likely source of subtle bugs. And requiring a special exception to the rules is not really desirable in the first place. --bbThere's a related problem where a public method is added to a base-class A (as in your example) but where the signature is *exactly* that of one existing in derived class B. If A actually calls that new method internally, "bad things"tm will almost certainly happen, since B never intended to effectively override the newly-added method in A. This is a very hard problem to isolate yet can be easily remedied by the compiler. The request was first made two or three years back, and once or twice since then: you make the "override" keyword *required*. When "override" is required, the compiler can easily trap this related type of hijacking and avoid such nasty surprises.That is a good point. The reason I haven't added it is because I'm not sure how annoying it will be to have to always add the 'override' keyword. It might be one of those things like exception specifications where everyone says it's a good idea but guiltily hate in secret <g>. Mitigating factors are private and final methods cannot be overridden.
Aug 08 2007
This is a very hard problem to isolate yet can be easily remedied by the compiler. The request was first made two or three years back, and once or twice since then: you make the "override" keyword *required*.I'm for this. I feel funny when I don't use "override".
Aug 06 2007
This post looks like a prime candidate for an article page on the D website (with "Const", "Memory Management", etc). Regan
Aug 06 2007
kris Wrote:Walter: There's a related problem where a public method is added to a base-class A (as in your example) but where the signature is *exactly* that of one existing in derived class B. If A actually calls that new method internally, "bad things"tm will almost certainly happen, since B never intended to effectively override the newly-added method in A. This is a very hard problem to isolate yet can be easily remedied by the compiler. The request was first made two or three years back, and once or twice since then: you make the "override" keyword *required*. When "override" is required, the compiler can easily trap this related type of hijacking and avoid such nasty surprises.if the function is overrided ONLY when the override keyword is there would prevent prevent any errors when such an action occurrs, but you also run into the bittersweet situation of hiding members of the base class.
Aug 06 2007
On Sun, 05 Aug 2007 11:47:18 -0700, Walter Bright wrote:I want to continue a bit in the Overloading/Inheritance thread which is getting a little long, on a closely related issue which I find to be important, but so rarely referred to that I had to come up with a name for it - hijacking.I'm just wondering what the NSA is making of this discussion :) -- Derek Parnell Melbourne, Australia "Down with mediocrity!"
Aug 06 2007
Derek Parnell wrote:On Sun, 05 Aug 2007 11:47:18 -0700, Walter Bright wrote:Hopefully, they'll analyze the site, get excited about D, and use D for their next generation software!I want to continue a bit in the Overloading/Inheritance thread which is getting a little long, on a closely related issue which I find to be important, but so rarely referred to that I had to come up with a name for it - hijacking.I'm just wondering what the NSA is making of this discussion :)
Aug 06 2007
Reply to Walter,Derek Parnell wrote:Fat chance, most of D's advantages don't exist in under ~5000 LOC and anything over that and the NSA won't touch it. Besides there isn't 20+ years of best practices in how to right secure software in D (as this is in C) SorryOn Sun, 05 Aug 2007 11:47:18 -0700, Walter Bright wrote:Hopefully, they'll analyze the site, get excited about D, and use D for their next generation software!I want to continue a bit in the Overloading/Inheritance thread which is getting a little long, on a closely related issue which I find to be important, but so rarely referred to that I had to come up with a name for it - hijacking.I'm just wondering what the NSA is making of this discussion :)
Aug 07 2007
BCS wrote:Reply to Walter,I'd think DBC would be a perk, if nothing else. Assuming the NSA currently uses C, that is. SeanDerek Parnell wrote:Fat chance, most of D's advantages don't exist in under ~5000 LOC and anything over that and the NSA won't touch it. Besides there isn't 20+ years of best practices in how to right secure software in D (as this is in C)On Sun, 05 Aug 2007 11:47:18 -0700, Walter Bright wrote:Hopefully, they'll analyze the site, get excited about D, and use D for their next generation software!I want to continue a bit in the Overloading/Inheritance thread which is getting a little long, on a closely related issue which I find to be important, but so rarely referred to that I had to come up with a name for it - hijacking.I'm just wondering what the NSA is making of this discussion :)
Aug 07 2007
Sean Kelly wrote:BCS wrote:I thought NSA used ADA it was designed for such purposes. -JoelReply to Walter,I'd think DBC would be a perk, if nothing else. Assuming the NSA currently uses C, that is. SeanDerek Parnell wrote:Fat chance, most of D's advantages don't exist in under ~5000 LOC and anything over that and the NSA won't touch it. Besides there isn't 20+ years of best practices in how to right secure software in D (as this is in C)On Sun, 05 Aug 2007 11:47:18 -0700, Walter Bright wrote:Hopefully, they'll analyze the site, get excited about D, and use D for their next generation software!I want to continue a bit in the Overloading/Inheritance thread which is getting a little long, on a closely related issue which I find to be important, but so rarely referred to that I had to come up with a name for it - hijacking.I'm just wondering what the NSA is making of this discussion :)
Aug 07 2007
Reply to janderson,Sean Kelly wrote:The only experience I have (yes I do have a tiny bit) is in C and is only about 500 loc.BCS wrote:I thought NSA used ADA it was designed for such purposes. -JoelReply to Walter,I'd think DBC would be a perk, if nothing else. Assuming the NSA currently uses C, that is. SeanDerek Parnell wrote:Fat chance, most of D's advantages don't exist in under ~5000 LOC and anything over that and the NSA won't touch it. Besides there isn't 20+ years of best practices in how to right secure software in D (as this is in C)On Sun, 05 Aug 2007 11:47:18 -0700, Walter Bright wrote:Hopefully, they'll analyze the site, get excited about D, and use D for their next generation software!I want to continue a bit in the Overloading/Inheritance thread which is getting a little long, on a closely related issue which I find to be important, but so rarely referred to that I had to come up with a name for it - hijacking.I'm just wondering what the NSA is making of this discussion :)
Aug 07 2007
janderson wrote:Sean Kelly wrote:By my understanding, Ada was largely intended for robust systems control, while I would guess that much of the code written at the NSA is for in-house problem solving and that the safety provided by Ada isn't typically necessary. I think it's likely that the NSA most often uses mainstream languages for the bulk of its work, tending towards systems-oriented languages for their speed. SeanBCS wrote:I thought NSA used ADA it was designed for such purposes.Fat chance, most of D's advantages don't exist in under ~5000 LOC and anything over that and the NSA won't touch it. Besides there isn't 20+ years of best practices in how to right secure software in D (as this is in C)I'd think DBC would be a perk, if nothing else. Assuming the NSA currently uses C, that is.
Aug 08 2007
The old aliasing trick will still cause problems. (The 'override' keyword won't solve the problem in the following case.) class A { void foo(int); void foo(long); } class B : A { alias A.foo foo; override void foo(int); } void bar(B b) { short val =3D 1; b.foo(val); //calls 'foo(int)' } Now 'foo(short)' is added to 'A': void bar(B b) { short val =3D 1; b.foo(val); //calls 'foo(short)' } Solutions: (1) The aliasing trick will be banned (argh). or (2) One can overload final functions only (ermmm). Or, to solve the hijacking problem once and for all: (3) No implicit type casting with function calls. Somehow (3) seems appealing (but I'm probably just too tired). I go to sleep now... ;) On Sun, 05 Aug 2007 21:47:18 +0300, Walter Bright = <newshound1 digitalmars.com> wrote:I want to continue a bit in the Overloading/Inheritance thread which i=s =getting a little long, on a closely related issue which I find to be =important, but so rarely referred to that I had to come up with a name==for it - hijacking. Hijacking is when code A depends on B, and then when seemingly unrelat=ed =code C is modified, then A's behavior silently changes. Here's an =example from C++: --A.h-- void foo(long i); --B.c-- #include "A.h" #include "C.h" ... foo(3); // calls A's foo(long) -------- Let's say A.h and C.h are developed by different people. In C.h, the =developer adds: --C.h-- void foo(int i); ----- This does something completely different from A.h's foo(long), because==they just happened to share the same name. Now, when B.c is recompiled=, =it's call to foo is silently *hijacked* by C.h's foo. Because of C++'s overloading rules and lack of modularity, there's no ==way to programmatically defend against this. Instead, one has to rely =on =coding conventions (such as using a unique package prefix name on all ==symbols, like A_foo() and C_foo()). So how does this relate to the overloading/inheritance issues? Conside=r:----A.d---- class A { ... } -----B.d---- import A; class B : A { void foo(long); } ... void bar(B b) { b.foo(3); // calls B.foo(long) } ---- Let's say A.d comes from some third party library. Now the developer o=f =A decides to add some functionality to class A, and adds the member =function foo(int): ----A.d--- class A { void foo(int); } ------------ Now our hapless B programmer has his calls to B.foo(long) silently =hijacked to A.foo(int) (under Java rules). I don't see any reasonable ==way for B to defend against this. Certainly, developer A doesn't have ==any idea who is deriving from A (and that's the point of polymorphism)=- =but should he be disallowed from adding *any* method names? And the =hapless B developer, he wrote class B years ago and no longer quite =remembers how it works, he just recompiles it and now it silently fail=s.So, this is one case where I feel C++ got it right, and Java didn't. (P.S. It's not a compiler implementation issue, nor is it a runtime =performance issue.)
Aug 10 2007
Kristian Kilpi wrote:The old aliasing trick will still cause problems. (The 'override' keyword won't solve the problem in the following case.) class A { void foo(int); void foo(long); } class B : A { alias A.foo foo; override void foo(int); } void bar(B b) { short val = 1; b.foo(val); //calls 'foo(int)' } Now 'foo(short)' is added to 'A': void bar(B b) { short val = 1; b.foo(val); //calls 'foo(short)' }I don't think this is a problem, because the B author explicitly and deliberately opened the door to this, therefore he is taking responsibility for it.
Aug 10 2007
Walter Bright wrote:Kristian Kilpi wrote:Yes and no. At the time the author wrote "alias A.foo foo;" they were allowing void foo(long), not void foo(short). Yes, they still "opened the door to this" because D's current behaviour is to pull all overloads past/present/future. Perhaps being able to specify overloads exactly would in some cases be of benefit, eg. alias A.foo(long) foo; ReganThe old aliasing trick will still cause problems. (The 'override' keyword won't solve the problem in the following case.) class A { void foo(int); void foo(long); } class B : A { alias A.foo foo; override void foo(int); } void bar(B b) { short val = 1; b.foo(val); //calls 'foo(int)' } Now 'foo(short)' is added to 'A': void bar(B b) { short val = 1; b.foo(val); //calls 'foo(short)' }I don't think this is a problem, because the B author explicitly and deliberately opened the door to this, therefore he is taking responsibility for it.
Aug 11 2007
Regan Heath wrote:Walter Bright wrote:Honestly, we need some ability to specify more of a function/method's signature in the general case anyhow. (Return type isn't really important, since it can't be different without at least one parameter difference) This would help with the super-aliasing case above, /and/ with the address operator. void foo (int); void foo (char[]); Currently: &foo => *(foo(int)) Proposed: &foo => *(foo(int)) or ambiguity error? &foo(int) => *(foo(int)) &foo(char[]) => *(foo(char[])) Currently: alias foo bar; // all foo's Proposed: alias foo bar; // all foo's alias foo(int) bar; // just this one alias foo(char[]) bar; // ditto The only thing that might get interesting is whether the compiler can easily distinguish (&foo()) as "take the address of a function foo with no params" versus "take the address of the result of function foo". (Is that even legal? Or useful?) -- Chris Nicholson-SaulsKristian Kilpi wrote:Yes and no. At the time the author wrote "alias A.foo foo;" they were allowing void foo(long), not void foo(short). Yes, they still "opened the door to this" because D's current behaviour is to pull all overloads past/present/future. Perhaps being able to specify overloads exactly would in some cases be of benefit, eg. alias A.foo(long) foo; ReganThe old aliasing trick will still cause problems. (The 'override' keyword won't solve the problem in the following case.) class A { void foo(int); void foo(long); } class B : A { alias A.foo foo; override void foo(int); } void bar(B b) { short val = 1; b.foo(val); //calls 'foo(int)' } Now 'foo(short)' is added to 'A': void bar(B b) { short val = 1; b.foo(val); //calls 'foo(short)' }I don't think this is a problem, because the B author explicitly and deliberately opened the door to this, therefore he is taking responsibility for it.
Aug 11 2007