【Ruby】【高级编程】面向对象


# 【【面向对象】】
#【实例变量】
=begin
实例变量是类属性,它们在使用类创建对象时就编程对象的属性。每个对象的属性是单独赋值的,和其他对象之间不共享。
在类的内部,使用@运算符访问这些属性,在类的外部,使用访问器方法的公共方法进行访问。
=end

#例子
class Box
#构造函数
def initialize(w,h)
@width,@height = w,h
end

#访问器方法
def printWidth
@width
end

def printHeight
@height
end
end

# 创建对象,初始化盒子的高度与宽度
box = Box.new(10,20)

#使用访问器方法
x = box.printWidth
y = box.printHeight

puts "盒子宽度:#{x}"
puts "盒子高度:#{y}"
=begin
盒子宽度:10
盒子高度:20
=end

# 例子 设置器
class Box
def initialize(w,h)
@width ,@height = w,h
end

def getWidth
@width
end

def getHeight
@height
end

#设置器
def setWidth=(value)
@width = value
end

def setHeight=(value)
@height = value
end
end

#创建对象
box = Box.new(10,20)

#使用设置器方法
box.setWidth = 30
box.setHeight = 50

#使用访问器方法
x = box.getWidth
y = box.getHeight
puts "盒子宽度:#{x}"
puts "盒子高度:#{y}"
=begin
盒子宽度:30
盒子高度:50
=end


# 【实例方法】
class Box
def initialize(w,h)
@width,@height = w,h
end

#实例方法
def getArea
@width * @height
end
end

box = Box.new(10,20)

a = box.getArea()
puts "Area of box is : #{a}" #Area of box is : 200


#【类方法& 类变量】
# =begin
# 类变量是在类的所有实例中共享的变量。换句话说,类变量的实例可以被所有的对象实例访问。类变量以两个 @ 字符(@@)作为前缀,类变量必须在类定义中被初始化,如下面实例所示。
# 类方法使用 def self.methodname() 定义,类方法以 end 分隔符结尾。类方法可使用带有类名称的 classname.methodname 形式调用
# =end
class Box
@@count = 0

def initialize(w,h)
@width,@height = w,h

@@count += 1
end

def self.printCount()
puts "Box count is #@@count"
end
end

#创建两个对象
box1 = Box.new(10,20)
box2 = Box.new(30,100)

#调用类方法输出盒子计数
Box.printCount() #Box count is 2


# 【to_s方法】返回对象的字符串表示形式。
class Box
def initialize(w,h)
@width,@height = w,h
end

def to_s
"(w:#@width,h:#@height)"
end
end

box = Box.new(10,20)

puts "String representation of box is : #{box}" #String representation of box is : (w:10,h:20)


# 【访问控制】
=begin
不在实例和类变量上应用任何访问控制。
三种,public private protected
public: 可被任意对象调用。默认情况下,方法都是public的,处理initialize总是private的。
private:不能被类外部访问或查看。只有类方法可以访问私有成员。
protected:只能被类及子类的对象调用。访问也只能在类及其子类内部进行。
=end

class Box
def initialize(w,h)
@width,@height = w,h
end

#实例方法默认是public的
def getArea
getWidth * getHeight
end

#定义私有的访问器方法
def getWidth
@width
end

def getHeight
@height
end

#make them private
private :getHeight,:getWidth

# 输出面积的实例方法
def printArea
@area = getWidth * getHeight
puts "box area is :#@area"
end

#让实例方法是受保护的
protected :printArea
end

box = Box.new(10,20)

#调用实例方法
a = box.getArea
#puts "area of box is : #{a}"

#尝试调用protected的实例方法
#box.printArea()
=begin
Area of the box is : 200
test.rb:42: protected method `printArea' called for #
<Box:0xb7f11280 @height=20, @width=10> (NoMethodError)
=end
# 【备注】因为此时既不在类的内部也不在子类的内部访问的。


# 【类的继承】
=begin
Ruby 不支持多继承,但是 Ruby 支持 mixins。mixin 就像是多继承的一个特定实现,在多继承中,只有接口部分是可继承的。
当创建类时,程序员可以直接指定新类继承自某个已有类的成员,这样就不用从头编写新的数据成员和成员函数。这个已有类被称为基类或父类,新类被称为派生类或子类。
=end

class Box
#构造期方法
def initialize(w,h)
@width,@height = w,h
end

#实例方法
def getArea
@width * @height
end
end

# 定义子类
class BigBox < Box
#添加一个新的实例方法
def printArea
@area = @width * @height
puts "Big box area is :#@area"
end
end

box = BigBox.new(10,20)

box.printArea() #Big box area is :200

# 【方法重载】

#定义父类
class Box
def initialize(w,h)
@width,@height = w,h
end

#实例方法
def getArea
@width * @height
end
end

#定义子类
class BigBox < Box
# 改变已有的getArea方法
def getArea
@area = @height * @width
puts "Big box area is : #@area"
end
end

box = BigBox.new(10,30)

box.getArea() #Big box area is : 300


# 【运算符重载】

class Box
def initialize(w,h)
@width,@height = w,h
end

def +(other) #定义+ 来执行 向量加法
Box.new(@width + other.width,@height + other.height)
end

def -@ #定义一元运算符 - 来对width height 取反
Box.new(-@width,-@height)
end

def *(scalar) #执行标量乘法
Box.new(@width*scalar,@height*scalar)
end
end



# 【冻结对象】
=begin
有时候,我们想要防止对象被改变。在 Object 中,freeze 方法可实现这点,它能有效地把一个对象变成一个常量。任何对象都可以通过调用 Object.freeze 进行冻结。冻结对象不能被修改,也就是说,您不能改变它的实例变量。
您可以使用 Object.frozen? 方法检查一个给定的对象是否已经被冻结。如果对象已被冻结,该方法将返回 true,否则返回一个 false 值
=end

=begin
class Box
def initialize(w,h)
@width,@height = w,h
end

def getWidth
@width
end

def getHeight
@height
end

def setWidth=(value)
@width = value
end

def setHeight=(value)
@height = value
end
end

box = Box.new(10,20)

box.freeze

if(box.frozen?)
puts "box obj is frozen obj"
else
puts "box obj is normal obj"
end

#尝试使用设置器方法
box.setWidth = 30
box.setHeight = 50

#使用访问器方法
x = box.getWidth
y = box.getHeight

puts "width of box is :#{x}"
puts "height of box is :#{y}"
=end


=begin
Box object is frozen object
test.rb:20:in `setWidth=': can't modify frozen object (TypeError)
from test.rb:39
=end

#【类常量】

class Box
BOX_COMPANY = "TATA Inc"
BOXWEIGHT = 10

def initialize(w,h)
@width,@height = w,h
end

def getArea
@width * @height
end
end

box = Box.new(10,20)

a = box.getArea()
puts "area of box is :#{a}"
puts Box::BOX_COMPANY
puts "Box weight is : #{Box::BOXWEIGHT}"
=begin
area of box is :200
TATA Inc
Box weight is : 10
=end


#【使用 allocate 创建对象】
=begin
可能有一种情况,您想要在不调用对象构造器 initialize 的情况下创建对象,即,使用 new 方法创建对象,在这种情况下,您可以调用 allocate 来创建一个未初始化的对象,如下面实例所示:
实例
#!/usr/bin/ruby -w

# 定义类
class Box
attr_accessor :width, :height

# 构造器方法
def initialize(w,h)
@width, @height = w, h
end

# 实例方法
def getArea
@width * @height
end
end

# 使用 new 创建对象
box1 = Box.new(10, 20)

# 使用 allocate 创建两一个对象
box2 = Box.allocate

# 使用 box1 调用实例方法
a = box1.getArea()
puts "Area of the box is : #{a}"

# 使用 box2 调用实例方法
a = box2.getArea()
puts "Area of the box is : #{a}"

尝试一下 »
当上面的代码执行时,它会产生以下结果:
Area of the box is : 200
test.rb:14: warning: instance variable @width not initialized
test.rb:14: warning: instance variable @height not initialized
test.rb:14:in `getArea': undefined method `*'
for nil:NilClass (NoMethodError) from test.rb:29
=end


#【类信息】
#
=begin

Ruby的 self 和 Java 的 this 有相似之处,但又大不相同。Java的方法都是在实例方法中引用,所以this一般都是指向当前对象的。而Ruby的代码逐行执行,所以在不同的上下文(context)self就有了不同的含义。让我们来看看下面的实例:.
实例
#!/usr/bin/ruby -w

class Box
# 输出类信息
puts "Class of self = #{self.class}"
puts "Name of self = #{self.name}"
end

尝试一下 »
当上面的代码执行时,它会产生以下结果:
Class of self = Class
Name of self = Box
这意味着类定义可通过把该类作为当前对象来执行,同时也意味着元类和父类中的该方法在方法定义执行期间是可用的。
=end



# coding=utf-8

# 【【面向对象】】
#方法、类、模块
=begin
1 方法返回值不需要声明,默认最后一行为返回值。但若有条件判断返回的情况,需要用return声明
2 方法中可使用别名“alias”方法生成的拷贝,即使元方法变化,别名拷贝也不会变化
3 当方法定义在类的外部,默认是private。当方法啊定义在类的内部,默认是public
=end
def show_alias
puts "before alias"
end

alias alias_foo show_alias

def show_alias
puts "after alias"
end

puts show_alias #after alias
puts alias_foo #before alias

#例子 类
class Person
def initialize(age,sex)
@age = age
@sex = sex
end

def age
@age
end

def sex
@sex
end

end

tom = Person.new(20,"boy")
puts tom.age #20
puts tom.sex #boy



# 【【方法、类、模块】】 【类】
class Person
def initialize(age,sex)
@age = age
@sex = sex
end

def age
@age
end

def sex
@sex
end

def say
puts "hello world"
end

#重定义方法
def say
puts "How are you?"
end

end


tom = Person.new(20,'boy')
#特定对象的方法
def tom.bye
puts "Goodbye"
end

puts tom.age #只有一个对应的方法会按照这个方法来,如果有多个重定义的,则按照最新的来。所以此时输出"How are you?"
puts tom.sex
puts tom.say #hello world
puts tom.bye #Goodbye

#重新打开类
class PersonOne
def say
puts "Hi!"
end
end

class PersonOne
def bye
puts "Bye!"
end
end

wxue = PersonOne.new
wxue.say #Hi!
wxue.bye #Bye!

# 更好的属性读写,=号的威力
#可用很多种方法对属性进行读写,但最方便的,对属性直接赋值
class PersonTwo
def age=(age)
@age = age
end

def age
@age
end
end

tom = PersonTwo.new
tom.age=(20)
puts tom.age #20

class PersonThree
def age=(age)
@age = age
end

def age
@age
end

end

wxue = PersonThree.new
wxue.age = 20
print "wxue.age=",wxue.age,"\n"

# 自动生成属性的读写操作attr_*
=begin
方法名 效果 例子 等价的代码
attr_reader 读方法 attr_reader :age def age
@age
end
attr_writer 写方法 attr_writer :price def age = (age)
@age = age
end
attr_accessor 读写方法 attr_accessor :age def age = (age)
@age = age
end
def age
@age
end
attr 读方法和
可选的写方法
(如果第二个参数是true)1.attr :age 1. 参见attr_reader
2.attr :age,true 2. 参见attr_accessor
=end

#例子
class Car
attr_accessor :wheel
end

class Bus < Car
attr_accessor :chaircount
end

bus22 = Bus.new
bus22.wheel = 4
bus22.chaircount = 25

puts bus22.wheel #4
puts bus22.chaircount #25

#【【方法、类、模块】】【模块】
#module没有实例,使用时把module混合到类中来使用

module FirstModule
def say
puts "Hello"
end
end

class ModuleTest
include FirstModule
end

test = ModuleTest.new
puts test.say #"Hello"

# 模块和类可以相互嵌套
module Human
class Boy
def say
puts "cool"
end
end
end

test = Human::Boy.new
test.say #cool

























































































































posted @ 2018-07-08 13:00  素人渔芙2017  阅读(222)  评论(0编辑  收藏  举报