Você está na página 1de 4

[music] The question of when it is good style to use subclassing is an important one, and you could have an entire

course on object oriented design. But here, I just want to answer the question for our simple example of points and color points by considering some alternatives that we could have pursued instead. So, remember what we did is we had a Point class that had several methods to find, like getters and setters for x and y, as well as from distance for the origin methods and we wanted a different class that was very similar. That was a ColorPoint class that had all of that, but also had a getter and setter for a color property. And then, we had to change our initialize method to make sure that, that color was properly initialized. So, it turns out here, subclassing worked very well, it was convenient to reuse all that code from, from Point. But in general, once programmers learn subclassing, they do often tend to overuse it. All right. Most people would agree that in large OOP applications, there tends to be more subclassing than there probably should be. So, let me show you what else you could do rather than subclassing in order to get code reuse, even though, in this case, as we'll see sub classing is actually perfectly good style. So, here's the first alternative, since we're in a dynamic language where we can change class definitions anywhere in our program. What if we, instead of creating a ColorPoint class, just went and added new things to the Point class. So, go into the point class, we know we can do this anywhere in our program. Add the color and color equal getter and setter methods. Change the initialized method, and by providing a default argument for the color field, all the old uses of the initialize method. All the old calls to new will continue to work. We'll just be creating a new instance variable that people didn't know was there before. So, you can do this. You can get away with this in Ruby. It's, it's often bad style if some other

library wrote the Point class, you could be messing up all sorts of invariance by going in and changing it. You are now requiring every point in your system to have these color properties, even if many of them don't need it, and it's kind of a non-modular change. If you add a color field and someone else adds a z-coordinate and someone else adds a string, which is the name of the Point. You're just bloating your objects with all these different things, and that's if they're separate. If they interact in any way, if any of the methods assume the other ones don't exist, then you get into conflicts and, and all sorts of strange things should happen. So, this will work, particularly for these sort of simple examples, but it's not a particularly modular change. If we want to, in any way, keep the idea of a ColorPoint separate from the idea of a Point. So, here's a second alternative. Instead of subclassing Point, we could just copy and paste the methods. Now, we wouldn't be relying on Point at all, so things would be very separate in modular. We would just define a class ColorPoint. And since it's such a short class, there isn't too much to it. You, you know it almost fits on the slide. I, I omitted the details of the initialized method here and we would just say a ColorPoint has 3 getters and 3 setters for x, y, and color. It has an initialize, it has this distFromOrigin method, which I literally copy and pasted from the Point class, and distFromOrigin2. Now, what's good about this is that now points and color points are completely separate. Any changes anyone makes to the Point class will have absolutely no effect on how any instance of ColorPoint. And the obvious disadvantage is that I copy and paste the code. So, I'm not getting any code reuse. If there was some bug in distFromOrigin, I've just duplicated that bug. If someone adds good new functionality to Point, I would have to go in and copy that over here. Otherwise, I wouldn't be able to use it. So, this is a typical trade-off of, do I want to re-use code or, do I want to make a copy and we generally prefer code re-use?

Here's the third alternative and this is the one that people in objected oriented languages tend do to little of which is instead of subclassing Point. What if instances of ColorPoint had inside of them an instance of Point, in an instance variable as part of their private state? So, here's how this would work. I would just define a class ColorPoint, the super class would just be an implicit object, I'm not going to use anything from the super class explicitly here. I would have color getters and setters. But then, the other instance variable I would have is pt here, short for Point. And I will initialize it here in the initialized method to hold a Point. So now, my methods x, x equal, y, y equal. Distfromorigin, distFromOrigin2 will not work as they did before, but I could just forward the message, just make a nested method call to the underlying Point. So, when someone had an instance of ColorPoint and they called the x method, that would be this code that you see here. That would just, the body would just send the same message, would just call the x method on the underlying Point. Now, the good thing about this is that it encapsulates inside of ColorPoint the fact that there's a point. It's an implementation detail. It would let us change certain things. For example, if in ColorPoint, we wanted the x and y coordinate to be called fu and bar, then we would just change the names of these methods, and it wouldn't matter that the methods were called something different than the Point class. The disadvantages are two-fold. First of all, it's not nearly as convenient to code reuse. All right, I have to create all these methods just to pass a method to some underlying thing. But, much more interesting is that now a ColorPoint really is not a Point. There is a method that we saw in Ruby actually agrees with me. It's this totally separate thing whose internal representation happens to include an instance of Point. So, this is an even bigger deal in languages with static type systems where it matters to us whether an instance of ColorPoint can have some type that instances of Point also have. And here they would, they would not. It's less of a big deal in a dynamically

type language like Ruby. But, if you see code like this for something like ColorPoint it is actually inferior style, subclassing works really well here. Subclass says, I really do want to inherit all the methods from Point, I'm just like a point except I have some new things and I need to change the definition of the initialized method. And that's why even this third alternative for color points is an inferior one. But as I mentioned before, often times in Ruby programs and in other object-oriented programming languages, you should be doing something like this. But sort of out of laziness or convenience or sloppy thinking, you end up using subclassing instead.