面向对象的编程(OOP)是最受欢迎的编程范式也就不足为奇了。 OOP实际上与我们认为的方式非常相似。我们的世界非常复杂,以至于我们对现实的看法被简化为一个像计算机程序一样简单的界面。我们看不到我们经过的每一棵独特的树。我们看到类似于树木类别的对象。拥有各种对象的低分辨率模型使我们能够与世界互动,而不会变得不堪重负。我们根据经验不断地更新世界模型。有时,由于悲剧,损失或错误的假设,我们必须对模型进行调试或完全重写。
但是,我们不仅在低分辨率上看到世界。我们也有复杂的高分辨率看法。回想起我祖父母的核桃树,带有轮胎秋千或我父母的梨树在后院返回一系列特定的回忆和感官信息。我可以“感觉到”树皮的质地,看到“叶子的颜色,并“品尝”水果的甜味。我非常了解这两棵树。
课程和实例
在OOP中,我们编写了称为 class 的低分辨率模型,该模型生成称为 实例 的高分辨率对象。扩展上面的类比,树是class
,我的祖父母的核桃树是instance
。我父母的梨树是树的另一个instance
class
。
班级
class Tree
end
Ruby中的示例是模型类的开始:树。班级名称在Ruby中总是大写和单数。 (为什么Ruby?虽然可以将许多语言用于OOP,但Ruby是专门为OOP创建的。)
OOP对象模型既包含数据(属性)和代码(方法)。该树类目前在这两个类别中都缺乏。属性存储在变量中。实例变量以@
开头,而类变量以@@
开头。属性是通过方法读取,书面或修改的。实例方法以def method_name
开头。类方法以def self.method_name
开头。
class Tree
def name= name
@name = name
end
def name
@name
end
end
虽然它仍然不多,但这里有一个可以创建和检索树名称的树类。第一个方法.name=
编写了实例变量:@name
。这称为Setter方法。第二种方法.name
读取实例变量:@name
。这称为getter方法。
实例
grandpas_tree = Tree.new
#=> #<Tree:0x00007f87799b9af8>
grandpas_tree.name = 'Grandpa\'s Tree'
#=> "Grandpa's Tree"
grandpas_tree.name
#=> "Grandpa's Tree"
grandpas_tree
#=> #<Tree:0x00007f87799b9af8 @name="Grandpa's Tree">
所以这是树的第一个实例。重命名树就像再次调用Setter方法一样容易。使用Getter方法验证。
grandpas_tree.name = 'Tire Swing Tree'
#=> "Tire Swing Tree"
grandpas_tree.name
#=> "Tire Swing Tree"
宏
getter和setter方法都是有用的,但是有一种更简单的方法。宏是编写代码的代码。特别有用的三个宏是attr_reader
(属性getter),attr_writer
(属性setter)和attr_accessor
(属性getter&setter)。
class Tree
attr_reader :name
attr_writer :name
end
以这种方式重构树类仍然提供与以前相同的功能。宏使用符号来表示它们访问的变量。
class Tree
attr_accessor :name
end
这是重构树类的最简单方法。现在可以有效地添加许多属性。
class Tree
attr_accessor :name, :type, :age, :height
end
自己
由于类将具有许多实例,因此self
一词是一种指定的关键字,用于访问方法中的给定实例。在类方法的开头还使用了自我来区分它们与实例方法。
class Tree
# macros
attr_accessor :name, :type
# class variable
@@all = []
# special instance method called when a new instance is created: Tree.new('Grandpa\'s Tree', 'walnut')
def initialize(name, type)
@name = name
@type = type
# the instance is shoveled into the @@all array upon initialization
@@all << self
end
# class method
def self.all
@@all
end
end
此更新的树类创建具有名称和类型属性的树实例。呼叫树。所有返回已创建的所有树实例的数组。使用方法链,tree.all.count将返回创建的树实例数。 (.count
方法是内置的Ruby。)
Tree.new('Mom\'s', 'pear')
#=> #<Tree:0x00007f877f837710 @name="Mom's", @type="pear">
Tree.new('Grandpa\'s', 'walnut')
#=> #<Tree:0x00007f87799b9af8 @name="Grandpa's", @type="walnut">
Tree.new('Christmas', 'white pine')
#=> #<Tree:0x00007f877f82d170 @name="Christmas", @type="white pine">
Tree.all
#=> [#<Tree:0x00007f877f837710 @name="Mom's", @type="pear">, #<Tree:0x00007f87799b9af8 @name="Grandpa's", @type="walnut">, #<Tree:0x00007f877f82d170 @name="Christmas", @type="white pine">]
Tree.all.count
#=> 2
遗产
继承创建一个类别的层次结构,通过该类别,儿童或子类可以访问父或超级类的所有属性和方法。要写继承,子类“比超级类别”:class Tree < Forest
。
class Forest
attr_accessor :location, :area, :protected_status
def protected
@protected_status = true
end
end
# The Tree class inherits attributes and methods from the Forest class.
class Tree < Forest
attr_accessor :name, :type
@@all = []
def initialize(name, type)
@name = name
@type = type
@@all << self
end
def self.all
@@all
end
end
虽然可能会为此示例而进行,但是当使用诸如ActiveRecord或Sinatra的库时,继承特别有用。诸如此类的库具有多种使代码干燥的方法,并允许程序员专注于编写针对单个应用程序的独特方法,而不是编写每个应用程序中相同的方法。
作为Ruby中的一般规则,方法以5行的限制为5行,并且类别以100行代码限制。这使课堂和方法变得过于复杂和难以管理。遵守此标准会鼓励最简单,最清洁的代码。
结论
类,实例,属性,方法,宏,自我和继承是OOP中的一些基础知识。这些工具允许程序员编写对周围世界建模的代码。这只是一个直觉,但我猜您今天会注意到更多的树木。