The alternative would be to have two separate functions That could be better or not, but it depends on the rest of your code - i.e. would you have to check and cast somewhere else then or not. If so, there is no sense doing that, if not, you might consider it. But that's not the point anyway.
ps. Java's way would be:
if (obj instanceof BUserObject) {
((BUserObject) obj).relinquishAll(); }
or
if (obj instanceof BUserObject) {
BUserObject user = (BUserObject) obj;
user.relinquishAll(); }
but if I'm pretty sure that obj really is instanceof BUserObject I don't even check that because I am sure and if I am wrong I am guaranteed an exception.
But do you really assert or guard your every cast? My each and every single cast? No, I admit I don't -- but then I do try to avoid casts But you don't understand, I make no point about casts but about operations which instead of throwing return a bogus value when they fail. I don't know D, don't know if there are other such operations so I write about casts.
"Casting often is a sign of a bad design." That is true, but often it is a sign of a language's bad design (think Java pre-1.5 collections) and you just have to cast.
BObject obj =...; if (auto user = cast(BUserObject) obj) { // set ownership details } else { throw new BovisException("... "); }
I see one thing here. This
BObject obj =...
is certainly followed by an expression you strongly expect to return a BUserObject in fact, probably a call to some DAO code, but still your own. Then I see a serious design flaw here, because that expression itself should have failed if it couldn't cook up a BUserObject out of your query - and that's where the problem is, not the cast which would always succeed (and you could use assert on that) if the problem was signaled where it happened.
Of course, I don't see the big picture so you might have a good reason to do that this way but from what you've shown it's a kind of situation I was writing last time. Not only problem is not signaled when it should be, but due to the cast returning a made up value (null) the bug is not discovered still and only your awareness of this cast atrocity protects from something even worse.
When I write Java code I don't assert or catch on every cast, I write code so that I don't have to. Prior to 1.5 there were problems with collections and such stuff, but thankfully they are no more. My Java code for your example would be just:
BUserObject user =...; //set ownwership
and... would give a valid object or throw, but not give anything invalid.
Of course I can still assert that the "impossible" doesn't happen if I want to.
If I really, really just wanted the cast succeed and cared for nothing else, that's what the assert contract is for. But do you really assert or guard your every cast? Then you're one of those heroes that can use C as well, after all you can check for every -1 that may be given to you instead of a valid value.
The problem is, people don't do that, and other problem is, you often want to deal with the problem not where it happens but much earlier on your call stack (that's what some people argue against Java's checked exceptions - that if you use them, you end up declaring Exception thrown from all and every method, or converting one exception to another just to throw your problem up the program logic to where it will be dealt with). That's why exceptions, checked or not, prevail over explicit checking for some bogus value.
Duck typing is a retarded name for something that does not exist. Its just plain old strong dynamic typing. But it does exist, unfortunately, Bad thing as it is. It does only check if a method for a given signature exists while real strong typing, dynamic or not would also check if that method is inherited from the correct superclass or implemented from the correct interface.
Try this somewhat overdramatic example: public interface ZipFile { public void explode(); } public interface NuclearBomb { public void explode(); }
Duck typing will accept an instance implementing NuclearBomb to call ZipFile's explode() while strong typing will not.
BTW, the Visual Editor folks have implemented static duck typing for Java, so it does not even have to be dynamic.
You should have an explicit type checking operator such as Java's instanceof. But you have another kind of problem here - if you "make a free use" in your code, whether instanceof or this antipattern then you have something wrong with your program design. Well designed program should not have to use this check except in some very special situations.
And seeing as how trying to use any members of a null is going to throw stuff anyway... I don't see any problem with it. You should see a problem because that null may go unnoticed through many calls and make an exception thrown miles away from where the real error is. Nothing more hostile to maintenance and debugging - countless hours have been spent on such nulls or -1s by programmers where an exception thrown from where the bug really was would require no time to find the bug and you could start fixing it right away.
That's a more general principle of programming - one of the (if not just *the*) most important, to *fail fast*. Crash your application or class or function as soon as you know you can't make good. I've seen too much atrocious code and hours wasted on debugging where instead of failing the author wanted their code to "survive" no matter what happens, so when they could not use a real value anymore, they resorted to a made up one - null, false and -1 among the favorites.
And if ObjectiveC version has a default abstract (or Smalltalk way throwing something akin to SubclassResponsibility) class for quiz than it is interface, isn't it? Well, poor man's interface.
But subclassing a real quiz implementation is even more dangerous than letting duck typing crash the system. If I implement (and thus override) addQuestion() then removeQuestion() should be overriden too or it will be executed completely incompatible with what addQuestion() does. What will it remove? Nothing? Something? Will it throw? No way to know, but it may accidentally remove something from another quiz!
Because D returns a null for a failed up/down-cast of objects, such an if statement effectively filters on inheritance of classes / implementation of interfaces. But it is atrocious! Such a thing should throw an exception, returning null is just so damned atrocious like those C functions returning -1 on failure. We suffered much of them and we suffer still and there are even remnants in Java (such as File.delete).
I implement Quizz interface - I don't need removeQuestion now, but I *have* to implement it, so I just throw UnsupportedOperationException from that method. Another thing to note: I can use a tool to find all methods that throw UnsupportedOperationException throughout my code and see whether they are really unsupported forever or I just forgot to implement something (I setup Eclipse so default method stubs throw that exception, not return silently some absurd value as Eclipse wants by default). I cannot use a tool to find all objects that miss a method that does not come from a declared interface or can I? Can anyone show me such a tool? And please note that it should have some kind of precognition as well - Java interfaces declared by a framework can have methods that are to be used later while actual framework code is not ready to call them.
Well, I hope the ";)" means you're not that serious. It's not about bugs, I don't believe that static typing prevents any more bugs from happening than a decent unit test suite would. In fact I don't believe that static typing along with TDD will let less bugs through than TDD on a dynamic language itself.
Second, you can always see if the method is there before calling it. I don't see it as a big deal, although I only used it a bit with python. (which keeps the usual syntax, object.likelymethod() ). I prefer the benefit of rapid development to verbosity.
Checking for a method is of no worth. If I get an object I hope to send a message to, and I cannot send then I'm hopeless anyway.
So called rapid development has some benefits for first time programmer, but it is in fact hostile to program maintenance and, in case of writing a library or framework to all of it's users as well. That's not about checking and throwing, that's about giving information to co-developers or users.
If one next line is quizz.removeQuestion("some question"); or, I suppose [quizz removeQuestion:@"some question"] for ObjC in Java it is impossible that the quizz object does not implement both methods, or the program will not compile. In ObjC OTOH it is possible, the program will compile and run until the removeQuestion message is actually passed to the object which might not happen for months if it's within a conditional branch which rarely gets executed.
Let's take it a bit further: I take your QUIZZ library, read up a bit then implement my own quiz type with addQuestion but without removeQuestion (because at first I don't need it and then I simply forget) and then give it to someone. They are happy and add more and more questions, but the time comes they want to remove one. They click remove and KABOOM goes their system. Why oh why? Because Quiz object should implement removeQuestion but it does not. Let's take the Java version now: I implement Quizz interface - I don't need removeQuestion now, but I *have* to implement it, so I just throw UnsupportedOperationException from that method. I forget about it - it is implemented after all, isn't it? So when the user wants to remove a question they see what exception was thrown and by which code, so they call me and shout why it is not implemented?:) No KABOOM, an obvious log entry.
It is typed, in that each object has a type, but methods can accept or return objects without restrictions on their type (imagine using Object more in Java and not needing explicit casts). On the other hand, you still have the choice to specify types explicitly, if you are more on the apprehensive side.
Or is it? It's a duck typed language then. Or, simply put, untyped. Of course, data has to have types, even Ruby cannot deny that one. But if the language does not have static type information it must resort to duck typing anyway. And duck typing is just a disaster to the maintainability of anything more than a throwaway script.
You don't just go around implementing objects for methods only caring about type compatibility. You are usually supposed to know that applying a certain method to a certain object makes sense in your program's architecture, types or lack thereof notwithstanding.
But I do. Whenever I am implementing a listener for a GUI event I do. Of course it has to do something useful, not just be type compatible but I'm depending on the declared interface I have to implement. I don't look into Swing's or SWT's source to find what methods on the object I provide might or might not be called, I just implement them. If I don't need them all (for example I know the mouse might be moved but no sense to drag it on a widget) I leave some empty, but I still have to provide it. If I was relying on source reading or documentation, I could miss that one (e.g. dragging) because I don't need or want it, but the framework would still try and call it when a user drags the mouse and my application would crash.
But if the software is also more verbose,
True, but this kind of verbosity is good because it brings information to the class' clients. Just by looking at a method declaration you know for sure what you need to provide and that you need to provide nothing more. And when someone is irresponsible enough to modify a published interface, you'll know this also as soon as you try to reuild your application against a new version.
less extensible
False. In fact it is more extensible with static typing and its advantages than without it, while protected against bad extending - i.e. breaking existing clients.
ps. Java's way would be: or but if I'm pretty sure that obj really is instanceof BUserObject I don't even check that because I am sure and if I am wrong I am guaranteed an exception. But do you really assert or guard your every cast? My each and every single cast? No, I admit I don't -- but then I do try to avoid casts But you don't understand, I make no point about casts but about operations which instead of throwing return a bogus value when they fail. I don't know D, don't know if there are other such operations so I write about casts. "Casting often is a sign of a bad design." That is true, but often it is a sign of a language's bad design (think Java pre-1.5 collections) and you just have to cast.
Of course, I don't see the big picture so you might have a good reason to do that this way but from what you've shown it's a kind of situation I was writing last time. Not only problem is not signaled when it should be, but due to the cast returning a made up value (null) the bug is not discovered still and only your awareness of this cast atrocity protects from something even worse.
When I write Java code I don't assert or catch on every cast, I write code so that I don't have to. Prior to 1.5 there were problems with collections and such stuff, but thankfully they are no more. My Java code for your example would be just: and
Of course I can still assert that the "impossible" doesn't happen if I want to. If I really, really just wanted the cast succeed and cared for nothing else, that's what the assert contract is for. But do you really assert or guard your every cast? Then you're one of those heroes that can use C as well, after all you can check for every -1 that may be given to you instead of a valid value.
The problem is, people don't do that, and other problem is, you often want to deal with the problem not where it happens but much earlier on your call stack (that's what some people argue against Java's checked exceptions - that if you use them, you end up declaring Exception thrown from all and every method, or converting one exception to another just to throw your problem up the program logic to where it will be dealt with). That's why exceptions, checked or not, prevail over explicit checking for some bogus value.
Try this somewhat overdramatic example:
public interface ZipFile { public void explode(); }
public interface NuclearBomb { public void explode(); }
Duck typing will accept an instance implementing NuclearBomb to call ZipFile's explode() while strong typing will not.
BTW, the Visual Editor folks have implemented static duck typing for Java, so it does not even have to be dynamic.
That's a more general principle of programming - one of the (if not just *the*) most important, to *fail fast*. Crash your application or class or function as soon as you know you can't make good. I've seen too much atrocious code and hours wasted on debugging where instead of failing the author wanted their code to "survive" no matter what happens, so when they could not use a real value anymore, they resorted to a made up one - null, false and -1 among the favorites.
But how do I subclass an interface? I do not.
And if ObjectiveC version has a default abstract (or Smalltalk way throwing something akin to SubclassResponsibility) class for quiz than it is interface, isn't it? Well, poor man's interface.
But subclassing a real quiz implementation is even more dangerous than letting duck typing crash the system. If I implement (and thus override) addQuestion() then removeQuestion() should be overriden too or it will be executed completely incompatible with what addQuestion() does. What will it remove? Nothing? Something? Will it throw? No way to know, but it may accidentally remove something from another quiz!
Well, I hope the ";)" means you're not that serious. It's not about bugs, I don't believe that static typing prevents any more bugs from happening than a decent unit test suite would. In fact I don't believe that static typing along with TDD will let less bugs through than TDD on a dynamic language itself.
Checking for a method is of no worth. If I get an object I hope to send a message to, and I cannot send then I'm hopeless anyway.
So called rapid development has some benefits for first time programmer, but it is in fact hostile to program maintenance and, in case of writing a library or framework to all of it's users as well. That's not about checking and throwing, that's about giving information to co-developers or users.
No, it is not strong typing, it is duck typing.
:) No KABOOM, an obvious log entry.
If one next line is quizz.removeQuestion("some question"); or, I suppose [quizz removeQuestion:@"some question"] for ObjC in Java it is impossible that the quizz object does not implement both methods, or the program will not compile. In ObjC OTOH it is possible, the program will compile and run until the removeQuestion message is actually passed to the object which might not happen for months if it's within a conditional branch which rarely gets executed.
Let's take it a bit further: I take your QUIZZ library, read up a bit then implement my own quiz type with addQuestion but without removeQuestion (because at first I don't need it and then I simply forget) and then give it to someone. They are happy and add more and more questions, but the time comes they want to remove one. They click remove and KABOOM goes their system. Why oh why? Because Quiz object should implement removeQuestion but it does not. Let's take the Java version now: I implement Quizz interface - I don't need removeQuestion now, but I *have* to implement it, so I just throw UnsupportedOperationException from that method. I forget about it - it is implemented after all, isn't it? So when the user wants to remove a question they see what exception was thrown and by which code, so they call me and shout why it is not implemented?
Or is it? It's a duck typed language then. Or, simply put, untyped. Of course, data has to have types, even Ruby cannot deny that one. But if the language does not have static type information it must resort to duck typing anyway. And duck typing is just a disaster to the maintainability of anything more than a throwaway script.
But I do. Whenever I am implementing a listener for a GUI event I do. Of course it has to do something useful, not just be type compatible but I'm depending on the declared interface I have to implement. I don't look into Swing's or SWT's source to find what methods on the object I provide might or might not be called, I just implement them. If I don't need them all (for example I know the mouse might be moved but no sense to drag it on a widget) I leave some empty, but I still have to provide it. If I was relying on source reading or documentation, I could miss that one (e.g. dragging) because I don't need or want it, but the framework would still try and call it when a user drags the mouse and my application would crash.
True, but this kind of verbosity is good because it brings information to the class' clients. Just by looking at a method declaration you know for sure what you need to provide and that you need to provide nothing more. And when someone is irresponsible enough to modify a published interface, you'll know this also as soon as you try to reuild your application against a new version.
False. In fact it is more extensible with static typing and its advantages than without it, while protected against bad extending - i.e. breaking existing clients.