6.001 Structure and Interpretation of Computer Programs. Copyright o 2004 by Massachusetts Institute of Technology 6.001 Notes: Section 14.1 Slide 14.1.1 Elements of ooP Last time we introduced the idea of object oriented systems Today, we want to build on those basics, looking at how we can expand object-oriented systems to deal with hierarchies of objects, to leverage the commonality of methods between different kinds of objects. We are going to see how the same ideas of abstraction allow us to control complexity in object oriented systems, much as they did in procedural systems. We are also going to show a version of a Scheme based object- oriented system. Note that this is not an optimal implementation of an object-oriented system compared to say Java or C++, but the goal is to show how one could create and manipulate an object-oriented system using the tools we have already developed. Our intent is to separate these issues; highlighting the concepts of object-oriented systems, while grounding those concepts in a specific instantiate Elements of ooP lide14.1.2 To start, let me remind you of what we have already seen. we hart data structure are trying to large system around a collection of objects. An object can be thought of as a"smart"data structure; Set of methods for manipulating state variables a set of state variables that describe the object; and an associated set of methods for manipulating those state variables. We expect Specifies the common behavior of entities our systems to have many different versions of the same kind of Instance object. For instance, think of bank system in which we might A particular object or entity of a given class have many different accounts. Each account would have a set of data values: current balance, overdraft protection, pending deposits. Thus there is the notion of an account as an abstract structure, and there is notion of different, specific versions of this abstract structure. Thus, we make a distinction. a class will define the common behavior of a kind of object in our ystem, the collection of things that are going to behave in the manner defined by those commonalities. Instances capture the specific details of an individual version of that class Our goal is to see how to structure computation within this new paradigm, in which the central units are"smart data structures. Thus, when we design a system we will tend to focus on the classes, as those are the basic building blocks of our system. The"programming of these systems will tend to focus on the interactions and behaviors of the classes: how should changes in one instance of an object affect other aspects of that object or other objects in the system? When we want to actually run our system, say to simulate a behavior, we will use the classes to create the instances that are particular versions of things, and then see how those specific instances interact
6.001 Structure and Interpretation of Computer Programs. Copyright © 2004 by Massachusetts Institute of Technology. 6.001 Notes: Section 14.1 Slide 14.1.1 Last time we introduced the idea of object oriented systems. Today, we want to build on those basics, looking at how we can expand object-oriented systems to deal with hierarchies of objects, to leverage the commonality of methods between different kinds of objects. We are going to see how the same ideas of abstraction allow us to control complexity in objectoriented systems, much as they did in procedural systems. We are also going to show a version of a Scheme based objectoriented system. Note that this is not an optimal implementation of an object-oriented system compared to say Java or C++, but the goal is to show how one could create and manipulate an object-oriented system using the tools we have already developed. Our intent is to separate these issues; highlighting the concepts of object-oriented systems, while grounding those concepts in a specific instantiation in Scheme. Slide 14.1.2 To start, let me remind you of what we have already seen. We are trying to organize a large system around a collection of objects. An object can be thought of as a “smart” data structure; a set of state variables that describe the object; and an associated set of methods for manipulating those state variables. We expect our systems to have many different versions of the same kind of object. For instance, think of bank system in which we might have many different accounts. Each account would have a set of data values: current balance, overdraft protection, pending deposits. Thus there is the notion of an account as an abstract structure, and there is notion of different, specific versions of this abstract structure. Thus, we make a distinction. A class will define the common behavior of a kind of object in our system, the collection of things that are going to behave in the manner defined by those commonalities. Instances capture the specific details of an individual version of that class. Our goal is to see how to structure computation within this new paradigm, in which the central units are “smart” data structures. Thus, when we design a system we will tend to focus on the classes, as those are the basic building blocks of our system. The “programming” of these systems will tend to focus on the interactions and behaviors of the classes: how should changes in one instance of an object affect other aspects of that object or other objects in the system? When we want to actually run our system, say to simulate a behavior, we will use the classes to create the instances that are particular versions of things, and then see how those specific instances interact
6.001 Structure and Interpretation of Computer Programs. Copyright o 2004 by Massachusetts Institute of Technology Slide 14.1.3 Recall from last time the example we used to demonstrate object- Space War Class Diagram oriented systems. That example was a system for simulating a simple"star wars"scenario. In that system, we had class ch as those shown here. We had a class for ships TORPEDO class for planets, a class for torpedoes, and some other classes that we have not shown here. recall that for each class. we had two sets of things internal state variables which characterized CLOCK-TICK the state of each instance of the class and a set of methods the things that the class able of doing. Those me were characterized by the instance accepting a message of the same name, then performing some interaction between different 4 objects within the system or changing the status of the internal state variables of an instance Space War Class Diagram Slide 14.1. 4 In order to make a point, I have changed slightly my definition of a torpedo. Last time a torpedo just used a position and a elocity, and it moved until it hit some thing, at which point it ANET exploded. A smarter torpedo might explicitly seek some target. and use a state variable like a proximity fuse, so that when the CLOck-Ic torpedo got close enough to its target it would explode One reason for introducing this is to notice that state variables within our instances could actually point to other instances. So the state variable for a target would point to another class, a ship n this case Slide 14.1.5 Space War class Diagram However, the real point we want to draw attention to in this diagram is the commonality, particularly the commonality fly, they both therefore have state information about positian between ships and torpedoes. Note that both of these objects can ORPEDO velocity, they both have methods that deal with position anand elocity; thus they have a lot of things in common, as well as CK-TICK having a few distinctive properties We know that a common theme in this course is capturing common patterns and abstracting them. so the issue here is Ships and torpedoes have some behavior that is the same whether we can do the same thing in an object-oriented system is there are way to capture this commonality? Can we take advantage of the fact that torpedoes and ships share a lot in common, and use that to build more modular systems?
6.001 Structure and Interpretation of Computer Programs. Copyright © 2004 by Massachusetts Institute of Technology. Slide 14.1.3 Recall from last time the example we used to demonstrate objectoriented systems. That example was a system for simulating a simple "star wars" scenario. In that system, we had class diagrams such as those shown here. We had a class for ships, a class for planets, a class for torpedoes, and some other classes that we have not shown here. Recall that for each class, we had two sets of things: internal state variables, which characterized the state of each instance of the class, and a set of methods, the things that the class was capable of doing. Those methods often were characterized by the instance accepting a message of the same name, then performing some interaction between different objects within the system or changing the status of the internal state variables of an instance. Slide 14.1.4 In order to make a point, I have changed slightly my definition of a torpedo. Last time a torpedo just used a position and a velocity, and it moved until it hit some thing, at which point it exploded. A smarter torpedo might explicitly seek some target, and use a state variable like a proximity fuse, so that when the torpedo got close enough to its target it would explode. One reason for introducing this is to notice that state variables within our instances could actually point to other instances. So the state variable for a target would point to another class, a ship in this case. Slide 14.1.5 However, the real point we want to draw attention to in this diagram is the commonality, particularly the commonality between ships and torpedoes. Note that both of these objects can fly, they both therefore have state information about position and velocity, they both have methods that deal with position and velocity; thus they have a lot of things in common, as well as having a few distinctive properties. We know that a common theme in this course is capturing common patterns and abstracting them. So the issue here is whether we can do the same thing in an object-oriented system. Can we take advantage of the fact that torpedoes and ships share a lot in common, and use that to build more modular systems?
6.001 Structure and Interpretation of Computer Programs. Copyright o 2004 by Massachusetts Institute of Technology Slide 14.1.6 Space War Class Diagram with Inheritance Conceptually we should be able to do this. Without worrying IMOBILE-THING about implementation details, let's first pull out that common pattern in our class diagram. Here is an abstraction of that common pattern, a new class called a mobile-thing. It has two state variables, position and velocity, and it has some common methods for dealing with those variables. These variables and methods will hold for any mobile object. We will, of course, clude a type tag for this new kind of class, as well. And th thus defi Slide 14.1.7 Space War class Diagram with Inheritance Given that new class, we can now create specializations. We can MOBILE-THING create a subclass. a torpedo is a particular kind of mobile thing It has all the properties of mobile things, but it also has characteristics that are particular to torpedoes. Similarly, a ship is a kind of mobile thing; it's a specialization that has, in addition to the properties of mobile things, other characteristics that matter only to ships Space War Class Diagram with Inheritance Slide 14.1.8 SHiP class is a specialization or As we start designing our system, we can begin to put together sub-class of the MOBILE -THING class hierarchies of class diagrams. We have base classes like mobile SHIP inherits the state an things. We also have some specializations or subclasses so that VELOCE havior of MOBILE-THING for example a ship is a mobile thing and should therefore inherit t he 5HTP and o PE o casses the state and behavior of a mobile thing, as well as having its own properties. In the other direction, we say that the mobile thing class is a super-class of the ship and torpedo classes Now we can start building a broader set of designs in which we have hierarchies of information captured in different I specializations of different classes of objects Slide 14. 1.9 Space War Class Diagram with Inheritance And as we fill out our class diagram we will have different IMOBILE-THING relationships between the classes. Torpedoes, for example, can sub-class sa special have a class as a link: targets are always going to be elements of SHIP inherits the state and the ship class behavior of MOBILE-THING Note that one of the advantages of creating super-classes is that we can nicely isolate the code for the methods of the super classes so that if we want to change one of those methods, we TORPEDO only need to worry about the implementation of the super-class, proxim ATTACK not about all of the specializations. If for example we decide to CLOCK-TICK change how things move, we don't have to search for all the move methods in the different subclasses, we need only change the method in the super-class This gives us a nice
6.001 Structure and Interpretation of Computer Programs. Copyright © 2004 by Massachusetts Institute of Technology. Slide 14.1.6 Conceptually we should be able to do this. Without worrying about implementation details, let's first pull out that common pattern in our class diagram. Here is an abstraction of that common pattern, a new class called a mobile-thing. It has two state variables, position and velocity, and it has some common methods for dealing with those variables. These variables and methods will hold for any mobile object. We will, of course, include a type tag for this new kind of class, as well. And this thus defines a new class. Slide 14.1.7 Given that new class, we can now create specializations. We can create a subclass. A torpedo is a particular kind of mobile thing. It has all the properties of mobile things, but it also has characteristics that are particular to torpedoes. Similarly, a ship is a kind of mobile thing; it's a specialization that has, in addition to the properties of mobile things, other characteristics that matter only to ships. Slide 14.1.8 As we start designing our system, we can begin to put together hierarchies of class diagrams. We have base classes like mobile things. We also have some specializations or subclasses so that for example a ship is a mobile thing and should therefore inherit the state and behavior of a mobile thing, as well as having its own properties. In the other direction, we say that the mobile thing class is a super-class of the ship and torpedo classes. Now we can start building a broader set of designs, in which we have hierarchies of information captured in different specializations of different classes of objects. Slide 14.1.9 And as we fill out our class diagram, we will have different relationships between the classes. Torpedoes, for example, can have a class as a link: targets are always going to be elements of the ship class. Note that one of the advantages of creating super-classes is that we can nicely isolate the code for the methods of the superclasses so that if we want to change one of those methods, we only need to worry about the implementation of the super-class, not about all of the specializations. If for example we decide to change how things move, we don't have to search for all the move methods in the different subclasses, we need only change the method in the super-class. This gives us a nice
6.001 Structure and Interpretation of Computer Programs. Copyright o 2004 by Massachusetts Institute of Technology modularization of the system, by isolating the common methods in a single place, for easy maintenance and change 6.001 Notes: Section 14.2 Slide 14.2.1 How to design interactions between objects o our first goal is to examine the paradigm of constructing Focus on classes objects ystems around objects, and for now we are going to ignore the Relationships between classe issue of how to describe these object systems in Scheme, we will f interactions tha instead initially focus on the abstract use of object-based instances of classes systems. Thus, we will primarily consider the classes of objects For now, assume the following interface to an object we might want in a system, and the range of interactions that we lask ) will need to support between objects. For now, we will simply assume that given an instance of a class, that is an object, we can send that object a message using the form (ask <arguments In other words we can use some Scheme interface(which we will define later)based on the ask procedure, which takes as arguments an object, a name of a method (something we want the object to do), and some set of arguments that specify details of the method, and ask will cause the object to execute the specified method. We will return to details of this shortly An initial class hierarchy lide14.2.2 We start with a class for people, which we call the person class Each instance of a person has two class variables, holding the persons first and last name. Each instance also has two methods. The say method causes the person to say something WHOAREYOU? (ask persom-1 HOAREYoUP) The whoareyou? method causes the person to indicate their first The class diagram for this class is shown in the slide. As well we will assume some constructor for making instances of the class(we will get to details of this shortly), and we can see how asking an instance of this class to say something or to identify au themselves causes actions in the system
6.001 Structure and Interpretation of Computer Programs. Copyright © 2004 by Massachusetts Institute of Technology. modularization of the system, by isolating the common methods in a single place, for easy maintenance and change. 6.001 Notes: Section 14.2 Slide 14.2.1 So our first goal is to examine the paradigm of constructing systems around objects, and for now we are going to ignore the issue of how to describe these object systems in Scheme; we will instead initially focus on the abstract use of object-based systems. Thus, we will primarily consider the classes of objects we might want in a system, and the range of interactions that we will need to support between objects. For now, we will simply assume that given an instance of a class, that is an object, we can send that object a message using the form (ask ). In other words, we can use some Scheme interface (which we will define later) based on the ask procedure, which takes as arguments an object, a name of a method (something we want the object to do), and some set of arguments that specify details of the method, and ask will cause the object to execute the specified method. We will return to details of this shortly. Slide 14.2.2 We start with a class for people, which we call the person class. Each instance of a person has two class variables, holding the person’s first and last name. Each instance also has two methods. The say method causes the person to say something. The whoareyou? method causes the person to indicate their first name. The class diagram for this class is shown in the slide. As well, we will assume some constructor for making instances of the class (we will get to details of this shortly), and we can see how asking an instance of this class to say something or to identify themselves causes actions in the system
6.001 Structure and Interpretation of Computer Programs. Copyright o 2004 by Massachusetts Institute of Technology Slide 14.2.3 Now we add a sub-class of person, called a professor. An initial class hierarchy Note that this class does not have any specific internal class variables. However, because it is a subclass of a person, it z-1'say '(helle there) should inherit the class variables of its superclass. In other words, professors also have a first and last name, because their person superclass instance has such variables. And professors PROFESSOR have the ability to say things by virtue of being a subclass of LECTURE person. Note that we again assume there is some constructor for making instances of a class(which should will see. take care of creating superclass instances as part of the process). Because of this hierarchy of classes, we should be able to ask the professor to say something, and it will use its inherited method from the person instance to do this An initial class hierarchy Slide 14.2, 4 PERSON (ask professor-1'WHOAREYOU?) In our little world, professors have no class variables of their own(ah, the irony!) but they do have two methods,a whoareyou? method and a lecture method. Notice that a WHOAREYOU? professor has its own whoareyou? method, distinct from the identically named method in person. If we ask a professor whoareyou? it will run its own method to answer the question, LECTURE with a different behavior. when a subclass has a method of the same name as a superclass, the subclass method is said to shadow the inherited method in the superclass instance Slide 14. 2.5 An initial class hierarchy Now in the world we are creating, it is traditional that when a professor lectures he starts every sentence with" Therefore e professor Snith An interesting question to consider when actually implementing the professor class is whether this lecture method is a distinct sk professor -1 LECTURE(the sky is method, or whether it shares structure with the underlying say +Therefore, the sky is blue method of the inherited person class. Conceptually, we would like to think that lecturing is a particular variant on saying Royd」 professor should"delegate"part indeed one simply says the word"Therefore"and then says the of the lecture method to a persons emaining text. This idea of using a superclass method to accomplish part of a method is called" delegation Note that this is an important requirement to place on an object system. The idea is that at a conceptual level, just as classes can be related to one another(e.g. via the subclass hierarchy ), so too can methods be related to one another, by this delegation idea. And at the implementation level, delegation can be seen as a mechanism that allows subclasses to specialize(and use )methods found in superclasses This has two important consequences. The first is that if we design our object system correctly, we will have a clean modularity of code, so that there is only one place to implement saying some thing, and thus only one place to worry about if we decide to change the manner in which this method executes. Secondly, we have an explicit indication (through the act of delegation that the lecture method and the say method are related conceptually. We will return to this point when we consider an explicit implementation of an object-oriented system in Scheme
6.001 Structure and Interpretation of Computer Programs. Copyright © 2004 by Massachusetts Institute of Technology. Slide 14.2.3 Now we add a sub-class of person, called a professor. Note that this class does not have any specific internal class variables. However, because it is a subclass of a person, it should inherit the class variables of its superclass. In other words, professors also have a first and last name, because their person superclass instance has such variables. And professors have the ability to say things by virtue of being a subclass of person. Note that we again assume there is some constructor for making instances of a class (which should, as we will see, take care of creating superclass instances as part of the process). Because of this hierarchy of classes, we should be able to ask the professor to say something, and it will use its inherited method from the person instance to do this. Slide 14.2.4 In our little world, professors have no class variables of their own (ah, the irony!) but they do have two methods, a whoareyou? method and a lecture method. Notice that a professor has its own whoareyou? method, distinct from the identically named method in person. If we ask a professor whoareyou? it will run its own method to answer the question, with a different behavior. When a subclass has a method of the same name as a superclass, the subclass method is said to shadow the inherited method in the superclass instance. Slide 14.2.5 Now in the world we are creating, it is traditional that when a professor lectures he starts every sentence with “Therefore”. An interesting question to consider when actually implementing the professor class is whether this lecture method is a distinct method, or whether it shares structure with the underlying say method of the inherited person class. Conceptually, we would like to think that lecturing is a particular variant on saying: indeed one simply says the word “Therefore” and then says the remaining text. This idea of using a superclass’ method to accomplish part of a method is called “delegation”. Note that this is an important requirement to place on an object system. The idea is that at a conceptual level, just as classes can be related to one another (e.g. via the subclass hierarchy), so too can methods be related to one another, by this delegation idea. And at the implementation level, delegation can be seen as a mechanism that allows subclasses to specialize (and use) methods found in superclasses. This has two important consequences. The first is that if we design our object system correctly, we will have a clean modularity of code, so that there is only one place to implement saying some thing, and thus only one place to worry about if we decide to change the manner in which this method executes. Secondly, we have an explicit indication (through the act of delegation) that the lecture method and the say method are related conceptually. We will return to this point when we consider an explicit implementation of an object-oriented system in Scheme
6.001 Structure and Interpretation of Computer Programs. Copyright o 2004 by Massachusetts Institute of Technology Slide 14.2.6 An initial class hierarchy Now, lets add another new class as a subclass of professor, this I PERSON define ap-I tmake-arrog mtor ed nfalliMte) one called an arrogant-prof. An arrogant-prof is distinguished by the fact that he ends everything he says with WHOAREYou - niee weather we are having.obviously The obvious(sorry!) way to do this is to have the arrogant profs method of saying simply be a delegation of saying to its PROFESSOR superclass(professor), with obviously tacked onto the end Note that we delegate one step up the superclass chain because LECTURE that is the only way arrogant-prof can eventually get to the person. The ar a pointer to its imme superclass, but not to superclasses higher in the chain. B I delegating one step up the chain, the ordinary inheritance mechanism will take over when the system determines that the professor doesn t have a say method of its own Slide 14.2.7 An initial class hierarchy Now an interesting issue arises if we ask an arrogant-prof to lecture. What should he say? One view is that, because PERSON (define ap-1 (make-arrag antpraf'Bed'Infallible) arrogant-prof has no lecture method, lecture'ing will be ask ap-1 ' LECTURE Inice weather we are havin)) handled by the method in the professor class, which in turn will WHOAREYOU? delegate to person after tacking on a" therefore". The result will LECTURE ARROGANT An initial class hierarchy Slide 14.28 But another view says that arrogant- prof inherits the lecture [PERSON defie ap-l (make -ar eg mtofBed'Infau he) method from professor, so conceptually the lecture method is are having) sitting there in the arrogant-prof class. As a result, the lecture OAREYou?+ Therefore,nie method should give arrogant-prof a chance to see whether it knows how to say something, rather than instantly delegating to a say method found up the superclass chain. And of course, arrogant-prof does know how to say something; it has a say method, one that should shadow the say method of a person As a result, asking an arrogant-prof to lecture, under this view, should result in the following sequence of events cant find a lecture method in arrogant-prof class; use the method from the superclass, professor the lecture method from professor asks the current instance(an arrogant-prof) to say the original stuff, with"" prepended to the front. Note what has changed and what hasnt under this view Lectureing is still saying something with"therefore"on the front, but now we are asking the current instance, an arrogant-prof, to do the saying, instead of handing it up the superclass chain the arrogant-prof has a say method, which works by adding obviously to the end of the statement and finally, delegating the resulting statement up the inheritance chain to the next say method that can be found(which turns out to be in the person class) The result is as shown a key issue, we will then see, is to decide as we build our object oriented system, how we want methods to inherit from other methods. Ideally we will want the ability to choose as a programmer, when we decide on our classes of
6.001 Structure and Interpretation of Computer Programs. Copyright © 2004 by Massachusetts Institute of Technology. Slide 14.2.6 Now, let’s add another new class as a subclass of professor, this one called an arrogant-prof. An arrogant-prof is distinguished by the fact that he ends everything he says with “obviously”. The obvious (sorry!) way to do this is to have the arrogantprof’s method of saying simply be a delegation of saying to its superclass (professor), with obviously tacked onto the end. Note that we delegate one step up the superclass chain because that is the only way arrogant-prof can eventually “get to” the person. The arrogant-prof has a pointer to its immediate superclass, but not to superclasses higher in the chain. By delegating one step up the chain, the ordinary inheritance mechanism will take over when the system determines that the professor doesn’t have a say method of its own. Slide 14.2.7 Now an interesting issue arises if we ask an arrogant-prof to lecture. What should he say? One view is that, because arrogant-prof has no lecture method, lecture’ing will be handled by the method in the professor class, which in turn will delegate to person after tacking on a “therefore”. The result will be as shown. Slide 14.2.8 But another view says that arrogant-prof inherits the lecture method from professor, so conceptually the lecture method is sitting there in the arrogant-prof class. As a result, the lecture method should give arrogant-prof a chance to see whether it knows how to say something, rather than instantly delegating to a say method found up the superclass chain. And of course, arrogant-prof does know how to say something; it has a say method, one that should shadow the say method of a person. As a result, asking an arrogant-prof to lecture, under this view, should result in the following sequence of events: • can’t find a lecture method in arrogant-prof class; use the method from the superclass, professor • the lecture method from professor asks the current instance (an arrogant-prof) to say the original stuff, with “therefore” prepended to the front. Note what has changed and what hasn’t under this view: Lectureing is still saying something with “therefore” on the front, but now we are asking the current instance, an arrogant-prof, to do the saying, instead of handing it up the superclass chain. • the arrogant-prof has a say method, which works by adding “obviously” to the end of the statement, and finally, delegating the resulting statement up the inheritance chain to the next say method that can be found (which turns out to be in the person class). The result is as shown. A key issue, we will then see, is to decide as we build our object oriented system, how we want methods to inherit from other methods. Ideally we will want the ability to choose as a programmer, when we decide on our classes of
6.001 Structure and Interpretation of Computer Programs. Copyright o 2004 by Massachusetts Institute of Technology objects, whether we want to delegate behaviors to specific superclasses, or to simply inherit behaviors by following up the chain of classes Slide 14.2.9 An initial class hierarchy Now lets add one final type of object to our system, a student. (define stud (make student "bert sesame)) tudents are al ways very polite, so they have their own say method, which prepends the words"Excuse me, but to the front ask stud SA not understand)) of everything they say. WHOAREYOU?)Exeuse me, bu An initial class hierarchy Slide 14.2.10 Now suppose we go back to our class diagram, and decide to PERSON tnam。 modify our classes. For example, we want students to have the ability to ask a question of a professor. And of course, we need to add the ability for a professor to answer which we choose do within the arrogant-prof class. But we also decide that occasionally even a professor might have the need to ask a question In terms of our object system, this simply would require redefining whatever mechanism we use to create instances. so that a new method is included in that class definition Slide 14211 An initial class hierarch Note that in this case, we want our objects to take several (ask std'question why does this rode work) arguments, in particular, both the question and the object to PERSON→ hoeld be obvious t which the question is being directed. Also note the use of ap-1 as an argument, meaning we want the actual instance, not just the name of that instance We still have to define how we want the arrogant-prof to PROFESSOR STUDENT respond. We choose to incorporate the following behavior. If the OUESTION question is being asked by a student, then the arrogant-prof will respond by saying this should be obvious to you ARROGANT-P ANSWER
6.001 Structure and Interpretation of Computer Programs. Copyright © 2004 by Massachusetts Institute of Technology. objects, whether we want to delegate behaviors to specific superclasses, or to simply inherit behaviors by following up the chain of classes. Slide 14.2.9 Now let’s add one final type of object to our system, a student. Students are always very polite, so they have their own say method, which prepends the words “Excuse me, but” to the front of everything they say. Slide 14.2.10 Now suppose we go back to our class diagram, and decide to modify our classes. For example, we want students to have the ability to ask a question of a professor. And of course, we need to add the ability for a professor to answer, which we choose to do within the arrogant-prof class. But we also decide that occasionally even a professor might have the need to ask a question. In terms of our object system, this simply would require redefining whatever mechanism we use to create classes and instances, so that a new method is included in that class definition. Slide 14.2.11 Note that in this case, we want our objects to take several arguments, in particular, both the question and the object to which the question is being directed. Also note the use of ap-1 as an argument, meaning we want the actual instance, not just the name of that instance. We still have to define how we want the arrogant-prof to respond. We choose to incorporate the following behavior. If the question is being asked by a student, then the arrogant-prof will respond by saying “this should be obvious to you
6.001 Structure and Interpretation of Computer Programs. Copyright o 2004 by Massachusetts Institute of Technology Slide 14.2. 12 An initial class hierarchy On the other hand, if the question is asked by another professor, PERSON→ Why are you asking me动 why does this to then the arrogant-prof will respond by saying" why a paper on QvESTION 4 LANSWER Slide 14.2.13 An initial class hierarch The reason for introducing this behavior is to provide an xample of a class method, in which the action of the method depends on the object that initiated it. In particular, to incorporate this behavior, the arrogant-profs answer method (akpx。f命容ox-1 PROEESSOR? will need to do something different depending on what kind of object ask the question in the first place: if it was a student then PRoFESSOR STUDENT we want to respond one way, whereas if it was a professor, we want to respond a different way low do we do this? In essence, we need a way of tagging"our ARROGAN下平 objects, to identify their type. Within an object-oriented system, we choose to do this by adding to our classes a" predicate ANSWER method, which responds to the question of whether the instance is of that specified type. Thus, we can ask an object if they are a student, or a professor. (Actually, if you think about this, you will realize that we need to be careful in how we do this, since asking a professor if he is a student could lead to an error if the fact that the professor object does not have a student? method is not handled properly. We will see a particular way of dealing with this issue later.) Lessons from our simple class hierarchy Slide 14.2. 14 tagging of instances So what are the lessons we can take away from this simple specifying class hierarchies and ensuring that instances design exercise? Well, we can see that as we design a system for creating superclass instances supporting the creation of object-oriented systems, we need inheriting of methods from class hierarchies delegation of methods to other instances within a class methods for dealing with · tagging of instances specifying class hierarchies and ensuring that instances create superclass instances inheriting of methods from class hierarchies delegation of methods to other instances within a class hierarchy We will return to these issues in detail in later parts of the lectures
6.001 Structure and Interpretation of Computer Programs. Copyright © 2004 by Massachusetts Institute of Technology. Slide 14.2.12 On the other hand, if the question is asked by another professor, then the arrogant-prof will respond by saying “why are you asking me about … I thought you published a paper on that topic” Slide 14.2.13 The reason for introducing this behavior is to provide an example of a class method, in which the action of the method depends on the object that initiated it. In particular, to incorporate this behavior, the arrogant-prof’s answer method will need to do something different depending on what kind of object ask the question in the first place: if it was a student then we want to respond one way, whereas if it was a professor, we want to respond a different way. How do we do this? In essence, we need a way of “tagging” our objects, to identify their type. Within an object-oriented system, we choose to do this by adding to our classes a “predicate” method, which responds to the question of whether the instance is of that specified type. Thus, we can ask an object if they are a student, or a professor. (Actually, if you think about this, you will realize that we need to be careful in how we do this, since asking a professor if he is a student could lead to an error if the fact that the professor object does not have a student? method is not handled properly. We will see a particular way of dealing with this issue later.) Slide 14.2.14 So what are the lessons we can take away from this simple design exercise? Well, we can see that as we design a system for supporting the creation of object-oriented systems, we need methods for dealing with: • tagging of instances • specifying class hierarchies and ensuring that instances create superclass instances • inheriting of methods from class hierarchies • delegation of methods to other instances within a class hierarchy We will return to these issues in detail in later parts of the lectures
6.001 Structure and Interpretation of Computer Programs. Copyright o 2004 by Massachusetts Institute of Technology 6.001 Notes: Section 14.3 Slide 14.3.1 How build an OoP system in Scheme? Now, lets revisit these ideas by looking at how one might build an actual object-oriented system in Scheme. We are going to intertwine the idea of building class systems in Scheme, with the idea of using classes as a design methodology. Although not optimal, we will use a language we understand(Scheme)as a basis for examining how to create procedures that support class based systems, while trying to abstract the general methods from the specifics of this implementation in Scheme How build an OOP system in Scheme? Slide 14.3.2 Objects: as procedures that take messages Here is our blueprint for making this happen. First of all, objects in our system, i.e. the particular instances, we will represent as bject instances are unique Scheme procedures Local State gives each object (each instance of a class procedures that accept messages as input. We will use the same idea we saw earlier, message-passing procedures that accept Each instance procedure has own local environment messages and cause changes to state variables as a function of those messages. One of the advantages of this choice is that each instance will be uniquely identified. We can use eq? to tell them apart, because each object instance will be a unique Scheme procedure with a local frame that captures its information as local state Each object or instance can be formed differently because it has a procedure that points to a local environment that captures the state information, just as we saw in the previous examples of the earlier lectures Thus we will represent instances as local procedures with local state captured in local environments Slide 14.3.3 How build an OOP system in Scheme? Instances, of course, are simply particular versions of a class. So we will also need in our system a way of defining classes, and we will use a particular convention. We will define a Scheme Object instances are unique Scheme procedures procedure called ma ke-something(e.g. make-person, Each instance procedure has own local environment make-professor). Inside of that procedure, that classes: Scheme make-<object procedures definition of a class. we need two things we will need a set of Methods returned in response to pendent arguments) methods that will be returned in response to messages, so the -Inheritance Rule telling what method to use class procedures will need to contain within themselves ways of ssages methods taking in a message and returning a local method The second thing we need is an inheritance chain, a way of telling the class what methods to use, and by this we mean not just the local method, but rather if the class is a subclass of some superclass, we need a convention for deciding how to inherit methods from that superclass. In the case of a professor, for example, we might have methods to deal with LECTURE or WHOAREYOU?, but we also want to inherit the method of saY from the superclass of persoN So we will need to set up conventions for inheriting methods from superclasses
6.001 Structure and Interpretation of Computer Programs. Copyright © 2004 by Massachusetts Institute of Technology. 6.001 Notes: Section 14.3 Slide 14.3.1 Now, let’s revisit these ideas by looking at how one might build an actual object-oriented system in Scheme. We are going to intertwine the idea of building class systems in Scheme, with the idea of using classes as a design methodology. Although not optimal, we will use a language we understand (Scheme) as a basis for examining how to create procedures that support class based systems, while trying to abstract the general methods from the specifics of this implementation in Scheme. Slide 14.3.2 Here is our blueprint for making this happen. First of all, objects in our system, i.e. the particular instances, we will represent as procedures that accept messages as input. We will use the same idea we saw earlier, message-passing procedures that accept messages and cause changes to state variables as a function of those messages. One of the advantages of this choice is that each instance will be uniquely identified. We can use eq? to tell them apart, because each object instance will be a unique Scheme procedure with a local frame that captures its information as local state. Each object or instance can be formed differently because it has a procedure that points to a local environment that captures the state information, just as we saw in the previous examples of the earlier lectures. Thus we will represent instances as local procedures with local state captured in local environments. Slide 14.3.3 Instances, of course, are simply particular versions of a class. So we will also need in our system a way of defining classes, and we will use a particular convention. We will define a Scheme procedure called make-something (e.g. make-person, make-professor). Inside of that procedure, that definition of a class, we need two things: we will need a set of methods that will be returned in response to messages, so the class procedures will need to contain within themselves ways of taking in a message and returning a local method. The second thing we need is an inheritance chain, a way of telling the class what methods to use, and by this we mean not just the local method, but rather if the class is a subclass of some superclass, we need a convention for deciding how to inherit methods from that superclass. In the case of a professor, for example, we might have methods to deal with LECTURE or WHOAREYOU?, but we also want to inherit the method of SAY from the superclass of PERSON. So we will need to set up conventions for inheriting methods from superclasses
6.001 Structure and Interpretation of Computer Programs. Copyright o 2004 by Massachusetts Institute of Technology Slide 14.3. 4 Steps toward our Scheme OOPs So here is the blueprint we are going to use throughout the rest 1. Basic Objects of this lecture. We will start by building basic objects, A. messages and methods convention B. self variable to refer to oneself determining the methods we need and the conventions for dealing with such methods. We will see why we need a 2. Inheritance particular way of getting a handle on the object itself as ar al superclass instances, and method directly in object, or get-method from argument to methods, as we will see in a set of examples B We will then turn to the notion of inheritance. how to build an C. delegation: explicitly use methods from intemal objects internal superclass, and then deal with getting methods from that 3. Multiple Inheritance object itself or from internal instances of superclasses. We will see that there are variations on inheritance that become important I when designing object-oriented systems Finally, we will turn to the notion of multiple inheritance, having objects that can inherit methods from different kinds of superclasses So we are going to use this blueprint both to build an object oriented system in Scheme, and to see how such ideas can be used in general to design systems around the concepts of objects as a tool for controlling complexity in large systems Slide 14.3.5 Today's Example World: People, Professors We are going to develop these ideas using the particular example Arrogant-profs, and Students we developed previously, with a world of people professors PERSON arrogant-profs and students. As we progress, we will see how these classes relate to one another in terms of superclasses and inheritance of methods To start. we design a first class. This means creating a cl diagram, and we will start with the simplest thing: a person Here is the definition for the person class. It has two internal variables, an fname and an lname. It also has some methods that it can handle: returning its name, and saying things< (since that is what a person"does") 1. Method convention Slide 14.3.6 The response to every message is a method Now we are ready to implement our first class. Remember we A method is a procedure that can be applied to actually do the work said our class will be characterized as a procedure which, when (define (make-porson fname Iname) species he person class invoked. will construct instances of the class Here is our make bda(》 trame) person procedure, which defines our person class ((eq? message CHANGE-MY-NRME) To set this up, we have to make some design choices. Remember that instances of a class do different kinds of things. It may (lambda (1ist-of-stuff) l1splay-nessage lIst-or-stutn simply want to return some information, e.g. its name. It may 锅AT) want to change internal information, e.g. change the name. Thus alse (no-nethod))))) ve need methods that return information and methods that change information, and here is our design choice. We are going to require the response of an instance to every message to be a method. This is simply a choice on our part, though we believe it will be a convenient one as we add capabilities to our system. Note that it says we can't just return a value, we return procedures, the application of which may then return a valu
6.001 Structure and Interpretation of Computer Programs. Copyright © 2004 by Massachusetts Institute of Technology. Slide 14.3.4 So here is the blueprint we are going to use throughout the rest of this lecture. We will start by building basic objects, determining the methods we need and the conventions for dealing with such methods. We will see why we need a particular way of getting a handle on the object itself as an argument to methods, as we will see in a set of examples. We will then turn to the notion of inheritance, how to build an internal superclass, and then deal with getting methods from that object itself or from internal instances of superclasses. We will see that there are variations on inheritance that become important when designing object-oriented systems. Finally, we will turn to the notion of multiple inheritance, having objects that can inherit methods from different kinds of superclasses. So we are going to use this blueprint both to build an object oriented system in Scheme, and to see how such ideas can be used in general to design systems around the concepts of objects as a tool for controlling complexity in large systems. Slide 14.3.5 We are going to develop these ideas using the particular example we developed previously, with a world of people, professors, arrogant-profs and students. As we progress, we will see how these classes relate to one another in terms of superclasses and inheritance of methods. To start, we design a first class. This means creating a class diagram, and we will start with the simplest thing: a person. Here is the definition for the person class. It has two internal variables: an fname and an lname. It also has some methods that it can handle: returning its name, and saying things (since that is what a person "does"). Slide 14.3.6 Now we are ready to implement our first class. Remember we said our class will be characterized as a procedure which, when invoked, will construct instances of the class. Here is our makeperson procedure, which defines our person class. To set this up, we have to make some design choices. Remember that instances of a class do different kinds of things. It may simply want to return some information, e.g. its name. It may want to change internal information, e.g. change the name. Thus we need methods that return information and methods that change information, and here is our design choice. We are going to require the response of an instance to every message to be a method. This is simply a choice on our part, though we believe it will be a convenient one as we add capabilities to our system. Note that it says we can't just return a value; we return procedures, the application of which may then return a value