Comments on: virtual insanity http://www.coriolinus.net/2008/06/25/virtual-insanity/ read, and be entertained Sun, 12 Sep 2010 18:15:26 +0000 hourly 1 http://wordpress.org/?v= By: Yev http://www.coriolinus.net/2008/06/25/virtual-insanity/#comment-1517 Yev Sun, 29 Jun 2008 15:30:09 +0000 http://www.coriolinus.net/?p=2156#comment-1517 "sealed" prevents the inheretance of the whole class. That prevents you from doing things like the template method pattern with default behavior, in which you want to firmly define the gist of class behavior, but leave the rest to subclasses. The fact that you had to read so much of a reference before getting to the "virtual" keyword, is probably more a fault of the reference. It's really a fairly basic thing, and usually dealt with early on. I actually didn't have library code in mind. If you're dealing with black box code, static inheritance keywords won't provide much security. I was thinking more of some imbecille coworker. For instance, let's say I write a structure with an Add keyword that adds things to the beginning of a sequence. I accept one as an argument to my method, and work based on that assumption. An imbecille coworker subclasses my code, but his Add method adds to the end. The problem is, that when implementing my method, I don't know WHOSE code I'll be using. Now, if I wanted to make my code generic, my parameter should have been an interface or an abstract class - then I would know that the only expectation my code has is what is documented in the interface. But when calling methods on an implementation, there's still that implicit assumption that you know which code you're calling. That's why you still can create subclasses that override non-vitual methods. You just can't call those methods when you're treating your subclass as its base class. I've had to switch from Java to C# a little under a year ago - and really, after the first week or two, it hasn't been a problem. If anything, it's forced me to think better about my design and architecture - where I expect customized behavior, and where I don't. “sealed” prevents the inheretance of the whole class. That prevents you from doing things like the template method pattern with default behavior, in which you want to firmly define the gist of class behavior, but leave the rest to subclasses.

The fact that you had to read so much of a reference before getting to the “virtual” keyword, is probably more a fault of the reference. It’s really a fairly basic thing, and usually dealt with early on.

I actually didn’t have library code in mind. If you’re dealing with black box code, static inheritance keywords won’t provide much security. I was thinking more of some imbecille coworker. For instance, let’s say I write a structure with an Add keyword that adds things to the beginning of a sequence. I accept one as an argument to my method, and work based on that assumption. An imbecille coworker subclasses my code, but his Add method adds to the end. The problem is, that when implementing my method, I don’t know WHOSE code I’ll be using. Now, if I wanted to make my code generic, my parameter should have been an interface or an abstract class – then I would know that the only expectation my code has is what is documented in the interface. But when calling methods on an implementation, there’s still that implicit assumption that you know which code you’re calling. That’s why you still can create subclasses that override non-vitual methods. You just can’t call those methods when you’re treating your subclass as its base class.

I’ve had to switch from Java to C# a little under a year ago – and really, after the first week or two, it hasn’t been a problem. If anything, it’s forced me to think better about my design and architecture – where I expect customized behavior, and where I don’t.

]]>
By: coriolinus http://www.coriolinus.net/2008/06/25/virtual-insanity/#comment-1515 coriolinus Sun, 29 Jun 2008 08:01:17 +0000 http://www.coriolinus.net/?p=2156#comment-1515 In Java, there's the <tt>final</tt> keyword. The equivalent in C# is <tt>sealed</tt>. If you want to ensure that no subclass redefines your method's behavior, you have that option. The problem with making non-virtual functions the default is simply that the default should be reasonable. I had to read through 600 pages of introductory C++ reference before I got to a part that even mentioned the virtual keyword; if I had tried to just dive in and start coding, I probably would have had more than a few hours of weird, inexplicable, head-banging bugs the first time I tried writing something significant. Also, the only case in which your code needs to deal with objects that you can't review the source of is when you're calling library code. Presumably, you trust the authors of the libraries that you use. If someone else uses your code as a library, and they override doSomethingInnocent to blow up your computer, that's a bug in <em>their</em> code, not yours. Anyone could write a subclass of list whose size() method works, and also reformats your hard drive; it's just that nobody would use it. In Java, there’s the final keyword. The equivalent in C# is sealed. If you want to ensure that no subclass redefines your method’s behavior, you have that option.

The problem with making non-virtual functions the default is simply that the default should be reasonable. I had to read through 600 pages of introductory C++ reference before I got to a part that even mentioned the virtual keyword; if I had tried to just dive in and start coding, I probably would have had more than a few hours of weird, inexplicable, head-banging bugs the first time I tried writing something significant.

Also, the only case in which your code needs to deal with objects that you can’t review the source of is when you’re calling library code. Presumably, you trust the authors of the libraries that you use. If someone else uses your code as a library, and they override doSomethingInnocent to blow up your computer, that’s a bug in their code, not yours. Anyone could write a subclass of list whose size() method works, and also reformats your hard drive; it’s just that nobody would use it.

]]>
By: Yev http://www.coriolinus.net/2008/06/25/virtual-insanity/#comment-1514 Yev Sun, 29 Jun 2008 04:59:15 +0000 http://www.coriolinus.net/?p=2156#comment-1514 You'll find the same insanity in C#, which was created <i>after</i> Java, so I'm not sure if it makes any language less modern. There is actually a very good reason for this behavior, because otherwise, one can do ungodly things like this: //Java public class MyInnocentClass { public void doSomethingInnocent() { System.out.println("All is well!"); } } If I'm a user of the above class, I can be pretty much assured, that that class will, well, do innocent stuff. It presents a contract of a sort, an expectation of how it will behave. So if I then have a method public void doStuff(MyInnocentClass c){ c.doSomethingInnocent(); } I should be pretty confident in what that method will do. But of course, someone can always extend MyInnocentClass, and change doSomethingInnocent to blow up my computer instead. Now, my code will have to deal with behavior that is entirely unexpected. And as a result, the behavior of my own code will be non-deterministic. So if every method of every class is virtual, you can never guarantee predictable behavior, because somewhere in your call stack, a method might do what you don't expect, because it's been modified in a subclass of a parameter. So I'm perfectly happy to define some methods virtual explicitly - because it means that I place no expectaions on what exactly those methods will do, and will not rely on them producing any one kind of behavior. You’ll find the same insanity in C#, which was created after Java, so I’m not sure if it makes any language less modern. There is actually a very good reason for this behavior, because otherwise, one can do ungodly things like this:

//Java
public class MyInnocentClass {
public void doSomethingInnocent() {
System.out.println(“All is well!”);
}
}

If I’m a user of the above class, I can be pretty much assured, that that class will, well, do innocent stuff. It presents a contract of a sort, an expectation of how it will behave. So if I then have a method

public void doStuff(MyInnocentClass c){
c.doSomethingInnocent();
}

I should be pretty confident in what that method will do. But of course, someone can always extend MyInnocentClass, and change doSomethingInnocent to blow up my computer instead. Now, my code will have to deal with behavior that is entirely unexpected. And as a result, the behavior of my own code will be non-deterministic. So if every method of every class is virtual, you can never guarantee predictable behavior, because somewhere in your call stack, a method might do what you don’t expect, because it’s been modified in a subclass of a parameter. So I’m perfectly happy to define some methods virtual explicitly – because it means that I place no expectaions on what exactly those methods will do, and will not rely on them producing any one kind of behavior.

]]>