【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










































































猜你喜欢

转载自www.cnblogs.com/suren2017/p/9279778.html