Ruby 开发(四) - 面向对象(上)

230 阅读6分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第9天,点击查看活动详情

一、面向对象

面向对象思想是上世纪 90 年代以来软件开发的主流思想,面向对象思想已经超过了程序语言本身,应用到了更加广泛的领域,如数据库系统、交互式界面、分布式系统网络管理和人工智能等。

现在主流的编程语言如 Java、Python、Go、PHP、C#、C++ 等都是面向对象语言。

面向对象 Object Oriented,使用对象来模拟现实世界的一种设计思想,整个面向对象思想的和核心就是对象

面向对象包含了几个非常重要的概念,对象、类、状态、行为、消息;

  • 对象:在面向对象思想中,对象就是我们要研究的所有事物,对象可以是任何事物,对象可以当做一个目标去观察它、了解它、操作它,也就是“面向”对象
  • 类:对象不是凭空创造出来的,它是由类创建出来的,类是一批具有相同特征的对象抽象总结出来的,可以将类看做是一个模板
  • 对象的状态:对象表现出来的状态,比如对象的属性信息
  • 对象的行为:每个对象都行为,行为也就是对象所能做的事情

在面向对象中,类与类之间可以是包含关系,也可以是继承关系。

面向对象的特征

面向对象编程思想是只将面向对象的思想应用于软件开发的一种核心思想,它是一种程序设计方法

在面向对象程序设计中,类抽象了现实世界中的类型的概念,现实中对象的状态以属性的形式在类中体现,对象的行为以方法的形式在类中体现

面向对象的三大特征分别是封装、继承和多态。

封装

封装就是隐藏类的数据成员,只向外部提供一些公用的操作接口,访问者只能通过这些接口操作类的成员,而不能直接对这些类的成员进行赋值等修改该操作,这样可以保证数据的完整性。

比如一个 Human 类,该类中保存了具体的姓名、年龄、性别等信息,如果不封装,只能以一个一个的变量进行传递,并且这些数据也没有任何规则,比如人的年龄肯定是大于 0 的,但是直接通过访问变量的形式可以传递一些负数进去,这些非常不容易控制数据的完整性和合理性。

继承

继承时面向对象中的一个关键特性,继承是指两个或者两个类以上之间的关系。

继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的属性和方法,或子类从父类继承方法,使得子类具有父类相同的行为。

子类的创建可以增加新数据、新功能,可以继承父类全部的功能,但是不能选择性的继承父类的部分功能。继承是类与类之间的关系,不是对象与对象之间的关系。

多态

多态也是相对类而言的,子类继承了父类的所有的基本特征,但是由于子类各自的独有属性,所以对于同一个继承自父类的基本特征也有不同的实现方式。

二、Ruby 中类的创建

在 Ruby 中使用 class 关键字声明一个类,并且以 end 关键字结尾,可以通过类名.new 的方式实例化一个对象。

class Hero
  puts "声明了一个 Hero 类"
end

# 实例化对象
hero = Hero.new
puts hero

执行上述代码,输出结果如下:

声明了一个 Hero 类
#<Hero:0x00007fdf7983ff80>

类实例化时会执行类中的表达式。

self 关键字

在 Ruby 的类中,self 关键字表示当前对象。

# 定义一个对象
class Animal
  puts self
  puts self.class

  def put
    puts self
    puts self.class
  end
end


# 实例化对象
animal = Animal.new

puts "调用put方法"
animal.put

执行上述代码,输出结果如下:

Animal
Class
调用put方法
#<Animal:0x00007faf630e2760>
Animal

在声明类的时候,self 表示当前类既 Animal,当实例化后的对象调用 put 方法时,此时的 self 表示实例化的对象既对象在内存中的地址。

追加类的操作

在 Ruby 中定义好一个类之后,还可以对其尽心个追加操作,也就是说再定义一个同名的类,对其进行添加功能,Ruby 会将两个或者多个同名的类合并使用。

# 定义一个对象
class Human
  def walk
    puts "Human can walk"
  end
end

class Human
  def run
    puts "Human can run"
  end
end


# 实例化一个对象
human = Human.new
human.walk
human.run

执行上述代码,输出结果如下:

Human can walk
Human can run

从运行结果来看,Ruby 将两个类进行了合并,不要把一个类的定义分贝拆分到各个地方,如果将类的实例化代码放在第二次定义类的前面

# 定义一个对象
class Human
  def walk
    puts "Human can walk"
  end
end

# 实例化一个对象
human = Human.new
human.walk
human.run

class Human
  def run
    puts "Human can run"
  end
end

执行上述代码,输出结果如下:

Human can walk
Traceback (most recent call last):
/ruby-oop/ex3.rb:13:in `<main>': undefined method `run' for #<Human:0x00007f8c0f05aa80> (NoMethodError)

类一定要先定义,再使用。

嵌套类的定义

嵌套类,实际就是在一个类的内部声明另一个类,形成嵌套的结构,不过在使用嵌套类的时候稍有差别,需要使用外部类的名字前面添加两个冒号来引用嵌套类的名称,比如要使用 Head 类就要写成这样 Animal::Head

# 定义一个对象
class Animal
  class Head
    def put
      puts "这是 Animal 内部类 Head 的 put 方法"
    end
  end
end

head = Animal::Head.new
head.put

执行上述代码,输出结果如下:

这是 Animal 内部类 Head 的 put 方法

特殊类的定义

Ruby 中还允许为某个特定的对象追加一些方法和属性,这些方法和属性封装到一个类中直接追加到对象中,这个类没有特定的方法名,所以不能作为普通的类使用,称之为特殊类。语法格式如下:

class << obj
# 类中的内容
end
class Animal

end

animal = Animal.new
class << animal
  def put
    puts "特殊类中的 put 方法被调用"
  end
end

animal.put

执行上述代码,输出结果如下:

特殊类中的 put 方法被调用

初定义 Animal 类时,类中的内容为空,通过特殊类追加了一个 put 方法。