DOC PREVIEW
UW CSE 341 - Lecture Notes

This preview shows page 1 out of 3 pages.

Save
View full document
View full document
Premium Document
Do you want full access? Go Premium and unlock all 3 pages.
Access to all documents
Download any document
Ad free experience
Premium Document
Do you want full access? Go Premium and unlock all 3 pages.
Access to all documents
Download any document
Ad free experience

Unformatted text preview:

CSE 341, Spring 2008, Lecture 21 SummaryStandard Disclaimer: These comments may prove useful, but certainly are not a complete summary of allthe important stuff we did in class. They may make little sense if you missed class, but hopefully will helpyou organize and process what you have learned.This lecture covers three topics, the last of which is essential to OO programming and will be consideredmore generally next time:1. “Duck typing” — a sort of conceptual approach to dynamically typed OO programming)2. Blocks, Procs, and iterators — Ruby’s convenient, pervasive but somewhat idiosyncratic use of functionclosures3. Sub c lassing, inheritance, and dynamic dispatch — the most essential aspect of OO programmingDuck TypingIn dynamically typed OO languages, one often implicitly assumes some object is an instance of a particularclass. But no type system prevents an instance of a different class, and if the other class “behaves enoughlike” the expected class, the code you are writing may still work. For example, if we write a method likedef double xx + xendwe may have “thought” the method expects an Integer, but it works for any class with a + method thatcan be passed self as its argument.On the one hand, this flexibility can allow more code reuse and can allow callers to use “similar” objectsof unexpected classes. You can write very flexible code by not explicitly testing whether an object is aninstance of a certain class. Instead, you call just the methods you need. On the other hand, this means farfewer code changes produce equivalent code. For example, for integers, x+x and x*2 are equivalent, but thismay not be true in general.This idea — that the “type” of a variable is based entirely on the methods used on that variable — issometimes called “duck typing.” This refers to the expression, “If it walks like a duck and quacks like aduck, it’s a duck.” One can make a philsophical argument: If all you know about ducks is that they walkand quack and you have something that walks and quacks, you cannot tell it is not a duck, so is there anyharm in supposing that it is one?Ruby’s ClosuresWhile Ruby has while loops and for loops not unlike Java, much Ruby code written in good style doesnot use them. Instead, many classes have methods that take blocks. These blocks are almost closures. Forexample, intege rs have a times me thod that takes a block and executes it the number of times you wouldimagine. For example,x.times { puts "hi" }prints "hi" 3 times if x is bound to 3 in the envioronment. To pass a block to a method, you put it in bracesafter the method call. The example above has no regular arguments, but a method can take any number ofregular arguments and then 0 or 1 block.Blocks are closures in the sense that they can refer to variables in scope where the block is defined. Forexample, after this program executes, y is bound to 10:y = 7[4,6,8].each { y += 1 }1Here [4,6,8] is an array with with 3 elements. Arrays have a method each that takes a block and executesit once for each element. Typically, however, we want the block to b e passed each array element. We dothat like this, for example to sum an array’s elements and print out the running sum at each point:sum = 0[4,6,8].each { |x|sum += xputs sum}When calling a method that takes a blo ck, you should know how many arguments will be passed to the blockwhen it is called. For the each method in Array, the answer is 1, but as the first example showed, you canignore some arguments by writing fewer variables between the | characters (or omitting them entirely).Many collections, including arrays, have a variety of block-taking methods that look very familiar tofunctional programmers. For example, inject is just like the fold we studied in ML:sum = [4,6,8].inject(0) { |acc,elt| acc + elt }The argument to inject is the initial accumulator. If you omit it, inject will use the 0th element of thearray as the initial accumulator and start with the next array element. Some other useful iterators (methodsthat take care of iterating through the elements in one way or another) are map and any?. In two lectures,we will learn how many of the iterators are actually defined in terms of each in a mixin so that they do nothave to be reimplemented for each collection.While many uses of blocks involve calling methods in the standard library, you can also define your ownmethods that take blocks. In fact, you can pass a block to any method. The method body calls the blockusing the yield keyword. For example, this code prints "hi" 3 time s:def foo xif xyieldelseyieldyieldendfoo true { puts "hi" }foo false { puts "hi" }To pass arguments to a block, you put the arguments after the yield, e.g., yield 7 or yield(8,"str").Blocks are not quite closures because they are not objects. We cannot store them in a field, pass themas a regular method argument, assign them to a variable, put them in an array, etc. (Notice in ML andScheme, we could do the equivalent things with closures.) However, Ruby has “real” c losures too: The classProc has instances that are closures. The method call in Proc is how you apply the closure to arguments,for example x.call (for no arguments) or x.call(3,4).To make a Proc out of a block, just write lambda { ... } where { ... } is any block. Interestingly,lambda is not a keyword. It is just a method in class Object (and every class is a subclass of Object, solambda is available everywhere) that creates a Proc out of a block it is passed. You can define your ownmethods that do this too, but we won’t go into the syntax that accomplishes this.Subclassing, Inheritance, and Dynamic DispatchSub c lassing is an essential feature of object-oriented programming. If class C is a subclass of D than everyinstance of C is also an instance of D. The definition of C can inherit the methods of D, i.e., they are part ofC’s definition too. Moreover, C can extend by defining new methods that C has and D doesn’t. And it canoverride methods, by changing their definition from the definition in the superclass. In Ruby, this is muchlike in Java. In Java, a s ublcass also inherits the field definitions of the superclass, but in Ruby fields arenot part of a class definition.2In the code posted with this lecture, we considered an example with the class Point and three differentsubclasses:• ColorPoint, which is like a Point except it also has a color field• ThreeDPoint, which is like a Point except it also


View Full Document

UW CSE 341 - Lecture Notes

Documents in this Course
Macros

Macros

6 pages

Macros

Macros

6 pages

Macros

Macros

3 pages

Mutation

Mutation

10 pages

Macros

Macros

17 pages

Racket

Racket

25 pages

Scheme

Scheme

9 pages

Macros

Macros

6 pages

Load more
Download Lecture Notes
Our administrator received your request to download this document. We will send you the file to your email shortly.
Loading Unlocking...
Login

Join to view Lecture Notes and access 3M+ class-specific study document.

or
We will never post anything without your permission.
Don't have an account?
Sign Up

Join to view Lecture Notes 2 2 and access 3M+ class-specific study document.

or

By creating an account you agree to our Privacy Policy and Terms Of Use

Already a member?