CSC302 2007S, Class 28: Ruby (1) Admin: * I'll send all of you a prototype solution to the last problem on the exam. You may not post it on the Web or share it with others. * Don't forget the CS table at lunch today. * I've rearranged the schedule a bit. * Today we'll discuss what you've learned from the readings. * Wednesday we'll do a lab. * Friday we'll consider Rails. (I'm still looking for a good Rails reading) * Office hours cancelled today. (Reason given in class.) Overview: * Rhetoric of Readings. * Java Basics Reviews. * Introspection in Ruby. * New Ruby Features. * Oddities of Ruby Syntax. /Rhetoric and Readings/ * Different than we've seen before * Why did they take this perspective? * Were they successful? +-------------------------------+--------------------------------+ | How does whytheluckystiff | He describes it as something | | approach the problem of | a lot like a spoken lang. | | describing Ruby? | | +-------------------------------+--------------------------------+ | No, I didn't ask you *how* | Perhaps he uses the | | he described Ruby, I asked | Socratic method. The idea | | what approach he takes. | behind this method is that if | | | you ask the right questions, | | | the student will realize that | | | he or she already knows the | | | answers. | +-------------------------------+--------------------------------+ | No, sorry, that's the other | | | reading. | | | | | * Back to Sam's formatting style * How does whytheluckystiff approach the problem of describing Ruby? * After the initial claim, just steps through the different "parts of speech" with a little bit of commentary * What it looks like * Why it makes sense * Why are there cartoon foxes? * To relieve the bordom of "here's a language feature; here's another language feature; here's another language feature" * How else would you introduce a language? * Threaten to kill them if they don't read through the boring stuff. * Choose an interesting "real world" example in such a way that you need to add each thing. * Hidden assumption in both readings: You will read with a Ruby interpreter open /Retreat to Java/ * What can go in a Java class? * variable declarations - a variable is something used to store values * In an object-oriented langauge, these are often called "fields" (or "attributes"), and are associated with objects * In Java, there are "normal fields" (instance fields) * a new copy for each object and "static fields" (class fields) * shared between all objects in the same class * static fields can also be "constants" using the "final" keyword * fields (and methods) have protection levels * some can be used only by objects in the class * some can be used by objects outside the class * methods * have a protection level: public, protected, ___, or private * can be static or instance * static methods cannot use instance variables * have parameters * constructor * how to build new objects * might throw exceptions * May also extend *one* other class * And implement as many interfaces as we'd like Example: A "Boxed" Integer public class BoxedInteger extends Object implements Comparable { // Class Fields static int numberOfBoxes = 0; // Object/Instance Fields int val; // Constructors public BoxedInteger(int initialValue) { ++numberOfBoxes; this.val = initialValue; } // Methods public int get() { return this.val; } public int set(int newval) { int tmp = this.val; this.val = newval; return tmp; } public static int howMany() { return this.numberOfBoxes; } public int compareTo(Object other) throws Exception { BoxedInteger bi = (BoxedInteger).other; return Integer.compare(this.val, bi.val); } } // class BoxedInteger How would we write this in Ruby? "I'm building a class named BoxedInteger" class BoxedInteger end "There is a class/static/shared field named numberOfBoxes" Notation: @@numberOfBoxes Does not need to be declared explicitly But initialize to 0 @@numberOfBoxes = 0 "There is an object/instance/normal field named val" Notation: @val Does not need to be declared explicitly "There is a one-parameter constructor that sets val to that param" def initialize(initialValue) @@numberOfBoxes = @@numberOfBoxes.next @val = initialValue end What does it mean that I can write class Foo def initialize(initialValue) @@numberOfBoxes = @@numberOfBoxes.next @val = initialValue end end class Foo @@numberOfBoxes = 0; end We're changing/extending the behavior of the class [rebelsky@dijkstra 501] ~ % irb irb(main):001:0> Integer.methods => ["inspect", "send", "class_eval", "clone", "public_methods", "protected_instance_methods", "__send__", "private_method_defined?", "equal?", "freeze", "methods", "instance_eval", "display", "dup", "object_id", "include?", "private_instance_methods", "instance_variables", "extend", "protected_method_defined?", "const_defined?", "instance_of?", "name", "eql?", "public_class_method", "hash", "id", "singleton_methods", "induced_from", "taint", "frozen?", "instance_variable_get", "autoload", "constants", "kind_of?", "to_a", "ancestors", "private_class_method", "const_missing", "type", "instance_method", "<", "protected_methods", "<=>", "instance_methods", "==", "method_defined?", "superclass", ">", "===", "instance_variable_set", "const_get", "is_a?", ">=", "respond_to?", "to_s", "<=", "module_eval", "class_variables", "allocate", "class", "public_instance_methods", "tainted?", "=~", "private_methods", "public_method_defined?", "autoload?", "__id__", "nil?", "untaint", "included_modules", "const_set", "method"] irb(main):002:0> irb(main):003:0* irb(main):004:0* irb(main):005:0* irb(main):006:0* irb(main):007:0* irb(main):008:0* irb(main):009:0* irb(main):010:0* irb(main):011:0* irb(main):012:0* irb(main):013:0* irb(main):014:0* irb(main):015:0* irb(main):016:0* irb(main):017:0* irb(main):018:0* irb(main):019:0* irb(main):020:0* irb(main):021:0* irb(main):021:0> clear NameError: undefined local variable or method `clear' for main:Object from (irb):21 from :0 irb(main):022:0> ^C irb(main):022:0> ^C irb(main):022:0> quit [rebelsky@dijkstra 502] ~ % clear [rebelsky@dijkstra 503] ~ % irb irb(main):001:0> class BoxedInteger irb(main):002:1> def initialize(initialValue) irb(main):003:2> @@numberOfBoxes = @@numberOfBoxes.next irb(main):004:2> @val = initialValue irb(main):005:2> end irb(main):006:1> end => nil irb(main):007:0> x = BoxedInteger.new(5) NameError: uninitialized class variable @@numberOfBoxes in BoxedInteger from (irb):3:in `initialize' from (irb):7:in `new' from (irb):7 from :0 irb(main):008:0> class BoxedInteger irb(main):009:1> @@numberOfBoxes = 0 irb(main):010:1> end => 0 irb(main):011:0> x = BoxedInteger.new(5) => # irb(main):012:0> class BoxedInteger irb(main):013:1> def howMany irb(main):014:2> @@numberOfBoxes irb(main):015:2> end irb(main):016:1> end => nil irb(main):017:0> x.howMany => 1 irb(main):018:0> BoxedInteger.howMany NoMethodError: undefined method `howMany' for BoxedInteger:Class from (irb):18 from :0 irb(main):019:0> y = BoxedInteger(3) NoMethodError: undefined method `BoxedInteger' for main:Object from (irb):19 from :0 irb(main):020:0> y = BoxedInteger.new(3) => # irb(main):021:0> x.howMany => 2 irb(main):022:0> y.howMany => 2 irb(main):023:0> irb(main):024:0* x.class => BoxedInteger irb(main):025:0> x.methods => ["object_id", "instance_of?", "instance_variables", "to_s", "dup", "private_methods", "__id__", "=~", "send", "class", "tainted?", "howMany", "singleton_methods", "eql?", "untaint", "kind_of?", "id", "instance_variable_get", "inspect", "nil?", "taint", "frozen?", "public_methods", "extend", "instance_eval", "to_a", "__send__", "clone", "protected_methods", "hash", "freeze", "is_a?", "==", "instance_variable_set", "type", "respond_to?", "===", "equal?", "methods", "display", "method"] irb(main):026:0> [].methods => ["send", "index", "collect", "[]=", "inspect", "all?", "<<", "reject!", "flatten", "slice", "&", "clone", "entries", "pop", "length", "public_methods", "transpose", "__send__", "equal?", "freeze", "indexes", "*", "detect", "zip", "map!", "uniq", "+", "fetch", "methods", "instance_eval", "values_at", "-", "rindex", "map", "display", "any?", "size", "sort", "dup", "shift", "object_id", "include?", "min", "instance_variables", "clear", "extend", "instance_of?", "|", "find_all", "eql?", "indices", "each", "id", "hash", "first", "flatten!", "slice!", "singleton_methods", "replace", "inject", "delete_at", "reverse", "nitems", "taint", "sort_by", "unshift", "instance_variable_get", "max", "frozen?", "fill", "kind_of?", "uniq!", "select", "to_a", "compact", "type", "last", "protected_methods", "partition", "<=>", "delete_if", "empty?", "==", "===", "each_index", "grep", "instance_variable_set", "sort!", "assoc", "is_a?", "to_ary", "respond_to?", "reject", "to_s", "class", "insert", "reverse!", "push", "tainted?", "=~", "private_methods", "delete", "__id__", "concat", "member?", "nil?", "untaint", "find", "pack", "join", "reverse_each", "each_with_index", "collect!", "rassoc", "method", "at", "[]", "compact!"] irb(main):027:0> x.methods.sort => ["==", "===", "=~", "__id__", "__send__", "class", "clone", "display", "dup", "eql?", "equal?", "extend", "freeze", "frozen?", "hash", "howMany", "id", "inspect", "instance_eval", "instance_of?", "instance_variable_get", "instance_variable_set", "instance_variables", "is_a?", "kind_of?", "method", "methods", "nil?", "object_id", "private_methods", "protected_methods", "public_methods", "respond_to?", "send", "singleton_methods", "taint", "tainted?", "to_a", "to_s", "type", "untaint"] irb(main):028:0> BoxedInteger.methods => ["inspect", "send", "class_eval", "clone", "public_methods", "protected_instance_methods", "__send__", "private_method_defined?", "equal?", "freeze", "methods", "instance_eval", "display", "dup", "object_id", "include?", "private_instance_methods", "instance_variables", "extend", "protected_method_defined?", "const_defined?", "instance_of?", "name", "eql?", "public_class_method", "hash", "id", "new", "singleton_methods", "taint", "frozen?", "instance_variable_get", "autoload", "constants", "kind_of?", "to_a", "ancestors", "private_class_method", "const_missing", "type", "instance_method", "<", "protected_methods", "<=>", "instance_methods", "==", "method_defined?", "superclass", ">", "===", "instance_variable_set", "const_get", "is_a?", ">=", "respond_to?", "to_s", "<=", "module_eval", "class_variables", "allocate", "class", "public_instance_methods", "tainted?", "=~"