4. Метапрограмиране
class << self
speaker \"Стефан Кънев\"
speaker \"Николай Бачийски\"
on_date \"20‐10‐2008\"
end
lectures.last.recap
class Vector
def initialize(x, y, z)
@x, @y, @z = x, y, z
end
def length
(@x * @x + @y * @y + @z * @z) ** 0.5
end
def to_s() “(#@x, #@y, #@z)” end
end
orientation = Vector.new 1.0, 0.0, 1.0
puts orientation.length
class Vector
attr_accessor :x, :y, :z
def initialize(x, y, z)
@x, @y, @z = x, y, z
end
end
class Vector
def +(other)
Vector.new self.x + other.x,
self.y + other.y,
self.z + other.z
end
def *(n)
Vector.new @x * n, @y * n, @z * n
end
end
class Fixnum
alias broken_equal? ==
def ==(other)
if (self.equal?(0) and other.equal?(1)) or
(self.equal?(1) and other.equal?(0))
true
else
self.broken_equal?(other)
end
end
end
pesho = Coin.new 0.50
def pesho.pick_up(person)
person.get_hopes_high
person.humiliate
person.make_sad
end
metaprogramming.inspect
class Student < ActiveRecord::Base
validates_presence_of :name, :fn, :email
validates_numericality_of :fn
validates_email :email
belongs_to :university
has_many :grades
has_many :courses, :through => :courses
has_and_belongs_to_many :groups
before_destroy do |student|
InformationMailer.deliver_destroyed(student)
end
end
html :xmlns => \"http://www.w3.org/1999/xhtml\" do
head do
title \"Registered students\"
style :type => \"text/css\" do
content \"* { font‐family: Verdana; }\"
end
end
body do
h1 \"Registered students
ul do
@students.each do |student|
li do
p student.name
unless student.url.nil?
a \"Personal website\", :href => student.url
end
end
end
end
end
end
class Person; end
class Programmer < Person; end
class Rubyist < Programmer; end
>> chunky = Rubyist.new
>> chunky.class
Rubyist
>> chunky.class.superclass
Programmer
>> chunky.class.ancestors
[Rubyist, Programmer, Person, Object, Kernel]
>> chunky.instance_of?(Rubyist), chunky.instance_of? Programmer
[true, false]
>> chunky.kind_of?(Rubyist), chunky.kind_of?(Programmer)
[true, true]
>> Rubyist < Person, Rubyist < Programmer, Person < Rubyist
[true, true, false]
respond_to?
class Vector
def initialize(x, y, z) @x, @y, @z = x, y, z end
def length() (@x * @x + @y * @y + @z * @z) ** 0.5 end
def method_missing(name, *args)
return Vector.new(‐@x, ‐@y, ‐@z) if name.to_sym == :invert
super
end
private
def sum() @x + @y + @z end
end
>> vector = Vector.new 1.0, 2.0, 3.0
>> vector.respond_to? :length
true
>> vector.respond_to? :invert
false
>> vector.respond_to? :sum
false
>> vector.respond_to?(:sum, true)
false
class Vector
attr_accessor :x, :y, :z
def initialize(x, y, z) @x, @y, @z = x, y, z end
end
>> vector = Vector.new 1.0, 2.0, 3.0
>> vector.instance_variable_get :@y
2.0
>> vector.instance_variable_set :@y, 5.0
5.0
>> vector.instance_variable_get :@y
5.0
>> vector.y
5.0
>> vector.instance_variables
[\"@z\", \"@y\", \"@x\"]
class Coin
def initialize(value)
@value = value
end
def pick_up(person)
person.enrich self.value
end
def put_on_train_rail!
self.flatten
end
end
pesho = Coin.new 0.50
gosho = Coin.new 1.00
def pesho.pick_up(person)
person.get_hopes_high
person.humiliate
person.make_sad
end
class << pesho
def pick_up(person)
person.get_hopes_high
person.humiliate
person.make_sad
end
end
class << pesho
attr_accessor :value
alias take_from_ground pick_up
end
>> pesho.value
0.50
>> pesho.take_from_ground(stefan)
:(
>> singleton_class = class << pesho
self
end
>> p pesho
#<Coin:0x3ec5cf4 @value=0.50>
>> p singleton_class
#<Class:#<Coin:0x3ec5cf4>>
>> p singleton_class != pesho.class
true
class Object
def singleton_class
class << self
self
end
end
end
>> pesho.singleton_class
eval
>> x, y = 5, 10
>> code = \"x + y\"
>> sum = eval(code)
>> puts sum
15
>> eval \"def square(x) x ** 2 end\"
>> puts square(10)
100
>> v = Vector.new 1.0, 2.0, 3.0
>> Vector.class_eval \"def sum() @x + @y + @z end\"
>> p v.sum
6.0
>> Vector.class_eval do
def sum()
@x + @y + @z
end
end
>> p v.sum
6.0
def add_name_method(klass, given_name)
klass.class_eval do
def name
given_name
end
end
end
>> add_name_method(Vector, \"I, Vector\")
>> v = Vector.new 1.0, 2.0, 3.0
>> p v.name
undefined method `given_name' for Vector
define_method
def add_name_method(klass, given_name)
klass.send(:define_method, :name) do
given_name
end
end
>> add_name_method(Vector, \"I, Vector\")
>> v = Vector.new 1.0, 2.0, 3.0
>> p v.name
\"I, Vector\"
Module
namespace
mix‐in
namespace
module PseudoMath
class Vector
def initalize(x, y) @x, @y = x, y end
end
def PseudoMath.square_root(number)
number ** 0.5
end
PI = 3.0
end
puts PseudoMath::PI
height = PseudoMath::Vector.new 3.0, 4.0
puts PseudoMath::square_root(5)
puts PseudoMath.square_root(5)
mix‐in
module Debug
def who_am_i?
\"#{self.class.name} (\\##{self.object_id})\" +
\" #{self.to_s}\"
end
end
class Coin
include Debug
end
>> coin = Coin.new
>> puts coin.who_am_i?
Coin (#33139900) #<Coin:0x3f35978>
module Unicode
def self.const_missing(name)
if name.to_s =~ /^U([0‐9a‐fA‐F]{4,6})$/
utf8 = [$1.to_i(16)].pack('U')
const_set(name, utf8)
else
raise NameError, \"Unitinitialized constant: #{name}\"
end
end
end
puts Unicode::U00A9
puts Unicode::U221E
puts Unicode::X
Генериране на XML
XML.new(STDOUT) do
html do
head do
title { \"Extrapolate me\" }
end
body(:class => 'ruby')
end
end
class XML
def initialize(out, indent=' ', &block)
@res = out
@indent = indent
@depth = 0
self.instance_eval(&block)
@res << \"\\n\"
end
def tag(name, attributes={})
end
?
alias method_missing tag
end
Game.new do
pencho = Singlerich.new('Pencho')
kuncho = Eigendiel.new('Kuncho')
kuncho.knife pencho
kuncho.bow pencho
kuncho.sword kuncho
pencho.kick kuncho
puts kuncho.health pencho.health
end
class Eigendiel < Monster
weapons :bow, :knife
def after_bow(other)
# special poison, doesn’t work on me
other.hurt 2 if !other.equal?(self)
end
end
class Singlerich < Monster
weapons :knife, :sword, :kick
def before_knife(other)
# kicks at the same time
kick other
end
end
class Monster
attr_reader :health, :name
BASIC_DAMAGE = 11
def initialize(name)
@name = name
@health = 100
end
def self.weapons(*weapons_list)
end
?
def hurt(amount)
@health ‐= amount
puts \"#{@name} is a loser!\\n\" if @health < 0
end
end
def self.weapons(*weapons_list)
weapons_list.each do |weapon|
weapon = weapon.to_s
define_method weapon do |whom|
send \"before_#{weapon}\", whom if self.class.method_def...
whom.hurt BASIC_DAMAGE
send \"after_#{weapon}\", whom if self.class.method_def...
end
end
end
Game.new do
pencho = Singlerich.new('Pencho')
kuncho = Eigendiel.new('Kuncho')
kuncho.knife pencho
kuncho.bow pencho
kuncho.bow kuncho
chuck = Singlerich.new(\"Chuck\")
def chuck.explode(whom)
whom.hurt 100
end
chuck.explode pencho
chuck.explode kuncho
end
0 comments
Post a comment