# class_eval
class User
end
User.class_eval do
attr_accessor :name
def hello
"hello"
end
end
user = User.new
user.name = "world"
puts user.name
puts user.hello
# module"s self
module Management
def self.track
"track"
end
end
class User
include Management
end
# User.track # => error
Management.track
# class_eval in project
# requirement: we need to execute a class method when module included
module Manegement
def self.included base #Manafement模块被其他类Included的时候会执行
base.extend ClassMethods #User类注入ClassMethod
base.class_eval do #打开User类
setup_attribute
end
end
# Manegement 内部模块 当引入Management的时候 会被引用为其他类的类方法
module ClassMethods
def setup_attribute
puts "setup_attribute"
end
end
end
class User
include Manegement #目的是在include Management 的时候执行一些方法或者设置
end
instance_eval
instance_eval 是所有类实例的方法
打开的是当前实例作用域
# instance_eval, instance methods and class methods
# 1. as a question
class User
end
User.class_eval do
def hello
"hello"
end
end
User.instance_eval do
def hi
"hi"
end
end
puts User.hi
user = User.new
puts user.hello
# puts user.hi #报错
# instance_eval, singleton_method
a = "xxx"
a.instance_eval do
def to_hello
self.replace("hello")
end
end
puts a.to_hello
# b = "world"
# b.to_hello # => error
# class_eval as instance_eval
class User
end
User.class_eval do
def hello
"hello"
end
# works same as instance_eval
def self.hi
"hi"
end
end
puts User.new.hello
puts User.hi
method_missing
当当前作用域上下文没有找到方法时就会调用
method_missing方法
# metho missing
#
# 1. how it works
# 2. ancestors
# 3. rails"s AR
class User
def hello
"hello from User"
end
def method_missing(name, *args)
"method name is #{name} ,parameters :#{args}"
end
end
user = User.new
puts user.hello
puts "-" * 30
puts user.hi("hello",19)
# class structure, method finding
class User
def panels
@panels ||= ["Profile", "Products"]
end
end
class Admin < User
end
puts Admin.ancestors
admin = Admin.new
p admin.panels
# 从下往上查找 在admin中查找 找不到往上找User 然后Object 然后Kernel 然后 BasicObject
Method Overwrite 方法覆盖
class和module可以重新打开
方法可以重定义
# 重新打开class
class User
def panels
@panels ||= ["Profile", "Products"]
end
end
class User
def panels
"overwrite"
end
end
puts User.ancestors
admin = User.new
p admin.panels
# 从下往上查找 在admin中查找 找不到往上找User 然后Object 然后Kernel 然后 BasicObject
# overwrite and re-open
class Array
def to_hello_word
"hello #{self.join(", ")}"
end
end
a = %w[cat horse dog]
puts a.to_hello_word
# overwrite and re-open
a = %w[cat horse dog]
puts a.join(",")
class Array
def join
"hello"
end
end
puts "-" * 30
puts a.join
Module
Array.ancestors # => [Array, Enumerable, Object, Kernel, BasicObject]
Enumerable.class # => Module
Module.class # => Class
# module acts linke a class
module Management
def company_notifies
"company_notifies from management"
end
end
class User
include Management
def company_notifies
puts super
"company_notifies from user"
end
end
p User.ancestors
puts "-" * 30
user = User.new
puts user.company_notifies
# module included sequence
module Management
def company_notifies
"company_notifies from management"
end
end
module Track
def company_notifies
"company_notifies from track"
end
end
class User
include Management
include Track
def company_notifies
puts super
"company_notifies from user"
end
end
p User.ancestors
puts "-" * 30
user = User.new
puts user.company_notifies
# 1 module included in module
# 2 module acts as class
module Management
def company_notifies
"company_notifies from management"
end
end
module Track
include Management
def company_notifies
puts super
"company_notifies from track"
end
end
p Track.ancestors
puts "-" * 30
include Track
puts company_notifies
# module"s class method
module Management
def self.progress
"progress"
end
# you need to include/extend/prepend to use this metod
def company_notifies
"company_notifies from management"
end
end
puts Management.progress
include vs prepend
include 把模块注入当前类的继承链(祖先链) 后面
prepend 把模块注入当前累的继承链(祖先链) 前面
# module include
# include
module Management
def company_notifies
"company_notifies from management"
end
end
class User
prepend Management
# include Management
def company_notifies
"company_notifies from user"
end
end
p User.ancestors
puts "-" * 30
user = User.new
puts user.company_notifies
# inheritance
class User
attr_accessor :name, :age
def initialize name, age
@name, @age = name, age
end
def panels
# ||= 操作符, 如果变量不存在 那么就赋值
@panels ||= ["Profile", "Products"]
end
end
class Admin < User
def panels
@panels ||= ["Profile", "Products", "Manage Users", "System Setup"]
end
end
user = User.new("user_1", 18)
p user.panels
puts "-" * 30
admin = Admin.new("admin_1", 28)
puts admin.name
p admin.panels
# 查看这个类的父类
p Admin.superclass
# class, methodclassUserattr_accessor:nameattr_accessor:age@@counter=0definitializename,age@name=name@age=age@@counter+=1enddefsay_hiputs"hello #{@name}, i am #{@age}"enddefself.get_counter@@counterendendputsUser.get_counteruser=User.new("Hello",18)user.say_hiputsUser.get_counter## Access Control 访问控制1.public2.protected3.private# class, methodclassUserattr_accessor:nameattr_accessor:agedefinitializename,age@name=name@age=ageenddefsay_helloputs"hello..."say_hisay_heyenddefsay_hiputs"hello #{@name}, i am #{@age}"enddefsay_heyputs"hey, i am #{@name}"endprotected:say_hi,:say_heyenduser=User.new("Hello",18)user.say_hello
# 变量交换
a = 1
b = 2
b,a = a,b
puts a
puts b
puts "-" * 30
x = [1, 2, 3]
a, b = x #默认会把数组中的值依次赋值给 a ,b
puts a
puts b
puts "-" * 30
x = [1, 2, 3]
a, *b = x #这里a会接受第一个元素 b用了*号 表示接受剩下所有的元素
puts a
p b
#output
2
1
------------------------------
1
2
------------------------------
1
[2, 3]
# block usage
def hello
puts "hello method start"
yield
yield
puts "hello method end"
end
hello {puts "i am in block"}
#output
hello method start
i am in block
i am in block
hello method end
# yield with parameter
def hello
puts "hello method start"
yield("hello","world")
puts "hello method end"
end
hello {|x,y| puts "i am in block,#{x} #{y}"}
#output
hello method start
i am in block,hello world
hello method end
# yield with paramter
def hello name
puts "hello method start"
result = "hello " + name
yield(result)
puts "hello method end"
end
hello("world"){|x| puts "i am in block,i got #{x}"}
#output
hello method start
i am in block,i got hello world
hello method end
# build in methods
["cat", "dog","frog"].each do |animal|
puts animal
end
puts "-" * 30
["cat","dog","frog"].each{|animal| puts animal}
#output
cat
dog
frog
------------------------------
cat
dog
frog
# build in methods
10.times do |t|
puts t
end
puts "-" * 30
("a".."d").each { |char| puts char}
#output
1
2
3
4
5
6
7
8
9
------------------------------
a
b
c
d
# varibale scope
# before ruby2.0
x = 1
[1, 2, 3].each { |x| puts x}
puts x # => x will be 3,which is incorrect
#output
1
2
3
1
如果是在ruby2之前的版本 那么外部的变量x会被改变
# varibale scope
# 如果是2.0版本之后 puts x会报错
sum = 0
[1, 2, 3].each { |x| sum += x}
puts sum
# puts x
#output
6
# block return value
class Array
def find
each do |value|
return value if yield (value)
end
nil
end
end
puts [1, 2, 3].find { |x| x == 2 }
#output
2
# block as named parameter
def hello name, &block
puts "hello #{name}, from method"
block.call(name)
end
hello("world") {|x| puts "hello #{x} form block"}
#output
hello world, from method
hello world form block
# yield with parameter
def hello
puts "hello method start"
yield("hello","world")
puts "hello method end"
end
hello {|x,y| puts "i am block ,#{x},#{y}"}
#output
hello method start
i am block ,hello,world
hello method end
# block_given?
def hello
if block_given?
yield
else
puts "hello from method"
end
end
hello
puts "-" * 30
hello {puts "hello from block"}
#output
hello from method
------------------------------
hello from block
# block can be closure
def counter
sum = 0
# 代码库接收了一个参数x 如果x没有定义那么x为1 然后 sum +=x
proc {|x| x = 1 unless x; sum +=x }
end
c2 = counter
puts c2.call(1) #1
puts c2.call(2)
puts c2.call(3)
# 这里 closure 为闭包
#
#output
1
3
6
# new method to create block
# name is required
hello = -> (name){"hello #{name}"}
puts hello.call("world")
puts "-" * 30
# name is required
hello3 = lambda {|name| "hello #{name}"}
puts hello3.call("world")
puts "-" * 30
hello2 = proc {|name| "hello #{name}"}
puts hello2.call
puts hello2.call("world")
# lambda和proc区别 proc可以不传参数 lambda 更像是一个方法,必须传递参数
#output
hello world
------------------------------
hello world
------------------------------
hello
hello world