SitePoint Sponsor

User Tag List

Results 1 to 8 of 8
  1. #1
    SitePoint Enthusiast jitao's Avatar
    Join Date
    Feb 2003
    Location
    Shanghai
    Posts
    42
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Question Can i declare a class twic in Ruby?

    Hi, I'm new to ruby and reading a book "Practical Ruby Projects". And I see some example codes like
    Code Ruby:
    require 'dl/import'
     
    class LiveMIDI
      ON  = 0x90
      OFF = 0x80
      PC  = 0xC0
     
      def initialize
        open
      end
     
      def note_on(channel, note, velocity=64)
        message(ON | channel, note, velocity)
      end
     
      def note_off(channel, note, velocity=64)
        message(OFF | channel, note, velocity)
      end
     
      def program_change(channel, preset)
        message(PC | channel, preset)
      end
    end
     
    if RUBY_PLATFORM.include?('mswin')
     
      class LiveMIDI
        module C
          extend DL::Importable
          dlload 'winmm'
        end
      end
     
    elsif RUBY_PLATFORM.include?('darwin')
      class LiveMIDI
        # Mac code here
      end
    elsif RUBY_PLATFORM.include?('linux')
      class LiveMIDI
        # Linux code here
      end
    else
      raise "Couldn't find a LiveMIDI implementation for your platform"
    end
    I'm quite confused. It looks that the "class LiveMIDI" is declared twice. Is it legal to declare a class at two different places?
    BYW, is there any method in ruby that can print out all the information of an object like "var_dump()" in php?
    Thank you!
    Last edited by jitao; Nov 10, 2009 at 21:20. Reason: format

  2. #2
    SitePoint Evangelist
    Join Date
    Feb 2006
    Location
    Worcs. UK
    Posts
    404
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    In Ruby the first instance of class defines the Class and the second modifies it. When you start with Ruby that sounds like a problem, but in fact is very powerful as it allows you to extend classes easily.

    Here is an example that demonstrates what is happening:
    Code:
    class MultiClassTest
      def initialize
        @multi_class = MultiClass.new
        puts "**_Starting_new_test_**"
        test_methods_exist
        test_method_one
        puts "\n"
      end
    
      def test_methods_exist
        test_method_exists('one')
        test_method_exists('two')
      end
    
      def test_method_one
        puts "Method one returns '#{@multi_class.one}'"
      end
    
      def test_method_exists(method_name)
        if @multi_class.methods.include?(method_name)
          puts "Method #{method_name} found"
        else
          puts "Method #{method_name} not found"
        end
      end
    end
    
    class MultiClass
      def one
        "one"
      end
    end
    
    MultiClassTest.new
    
    class MultiClass
      def two
        "two"
      end
    end
    
    MultiClassTest.new
    
    class MultiClass
      def one
        "cheese"
      end
    end
    
    MultiClassTest.new
    This uses two classes. MultiClass is the class we are experimenting with, and MultiClassTest lets us easily run the same tests repeatedly. If you run the code you should get this output:
    Code:
    **_Starting_new_test_**
    Method one found
    Method two not found
    Method one returns 'one'
    
    **_Starting_new_test_**
    Method one found
    Method two found
    Method one returns 'one'
    
    **_Starting_new_test_**
    Method one found
    Method two found
    Method one returns 'cheese'
    As you can see, when MultiClassTest.new is first called only the method 'one' exists. The second time the second method 'two' has been added to the class. The third time the method 'one' has been overwritten with a new definition.

    This also demonstrates one use of the 'methods' method which returns an array of all the methods exisiting for an object. RDoc can give you more information and is used to generate the core API information.

  3. #3
    SitePoint Enthusiast jitao's Avatar
    Join Date
    Feb 2003
    Location
    Shanghai
    Posts
    42
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thank you for your kind reply. It really helps me get better understanding of ruby. But I didn't read anything like your reply in Ruby books. Do you know any tutorial/books that gives more samples about manipulating classes this way?

  4. #4
    SitePoint Evangelist
    Join Date
    Feb 2006
    Location
    Worcs. UK
    Posts
    404
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Have a look at the "Programming Ruby" Chapter 3:

    http://www.ruby-doc.org/docs/Program...t_classes.html

    The section just before "Inheritance and Messages"

    In Ruby, classes are never closed: you can always add methods to an existing class. This applies to the classes you write as well as the standard, built-in classes. All you have to do is open up a class definition for an existing class, and the new contents you specify will be added to whatever's there.

    This is great for our purposes. As we go through this chapter, adding features to our classes, we'll show just the class definitions for the new methods; the old ones will still be there. It saves us having to repeat redundant stuff in each example. Obviously, though, if you were creating this code from scratch, you'd probably just throw all the methods into a single class definition.

  5. #5
    SitePoint Wizard
    Join Date
    Mar 2001
    Posts
    3,537
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Also, note that any new methods added to a class can be called by objects created prior to adding the new method:

    Code Ruby:
    class A
      def greet
        puts 'hi'
      end
    end
     
    a1 = A.new
    a1.greet   #hi
     
    class A
      def say_goodbye
        puts "bye"
      end
    end
     
    a2 = A.new
    a2.greet  #hi
    a2.say_goodbye  #bye
     
    a1.say_goodbye  #bye

    You can also reopen ruby's built in classes:

    Code Ruby:
    class String
      def greet
        puts "Hi.  I'm a talking string."
      end
    end
     
    str = "apple"
    str.greet  #Hi.  I'm a talking string.
    #equivalently:
    "apple".greet  #Hi.  I'm a talking string.
     
    puts str.reverse   #elppa

    Ruby goes even one step further. You can add methods to a single object, which means that two objects, even though they are from the same class, can have different methods. Here is an example:

    Code Ruby:
    class A
      def greet
        puts 'hi'
      end
    end
     
    a1 = A.new
    a1.greet  #hi
     
    a2 = A.new
    a2.greet  #hi
     
    def a2.say_goodbye
      puts "bye"
    end
     
    a2.say_goodbye  #bye
    a1.say_goodbye  
     
    --output:--
    undefined method `say_goodbye' for #<A:0x2506c> (NoMethodError)
    Yes, ruby is a wild, crazy language.

    As for books, I can recommend David Black's new book "The Well Grounded Rubyist". It's not a beginners book; it's probably an advanced beginner to intermediate book and would be a good second book on ruby. Not only that, David Black is one heck of a nice guy who frequently responds to ruby questions on the internet.

  6. #6
    SitePoint Wizard
    Join Date
    Mar 2001
    Posts
    3,537
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    BYW, is there any method in ruby that can print out all the information of an object like "var_dump()" in php?
    Ruby has a standard library called YAML, which is used to "serialize objects" in order to write them text files to make them persistent. However, YAML is in human readable form, so you could use that:

    Code Ruby:
    require 'yaml'
     
    class A
      def initialize
        @x = 10
        @y = "hello"
      end
     
      def greet
        puts 'hi'
      end
    end
     
    a1 = A.new
    str = YAML.dump(a1)
    puts str
     
    output
    --- !ruby/object:A 
    x: 10
    y: hello
     
     
    hash = {'a', 1, 'b', 2}
    puts YAML.dump(hash)
     
    output:
    --- 
    a: 1
    b: 2

  7. #7
    SitePoint Wizard
    Join Date
    Mar 2001
    Posts
    3,537
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Whoops. There are some easier ways.

    1) There is a method called 'inspect' that you can call directly on an object; or you can use a syntax like puts:

    Code Ruby:
    hash = {'a', 1, 'b', 2}
    p hash
     
    class A
      def initialize
        @x = 10
        @y = "hello"
      end
     
      def greet
        puts 'hi'
      end
    end
     
    a = A.new
    p a
     
    --output:--
    {"a"=>1, "b"=>2}
    #<A:0x24ff4 @x=10, @y="hello">

    2) The pp standard library module is a pretty printer, which uses p and also adds some nicer formatting. In this case, the output is the same as the previous example, but if you have a larger data structure with more output, pp will format things nicer.

    Code Ruby:
    require 'pp'
     
    class A
      def initialize
        @x = 10
        @y = "hello"
      end
     
      def greet
        puts 'hi'
      end
    end
     
    a1 = A.new
    pp a1
     
    hash = {'a', 1, 'b', 2}
    pp hash

  8. #8
    SitePoint Enthusiast jitao's Avatar
    Join Date
    Feb 2003
    Location
    Shanghai
    Posts
    42
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hi, thank you ReggieB and 7stud. Your replies really help me clarify those points. Now I'm reading the Programming Ruby and would come back to you later.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •