ruby中的过程和数据抽象

ruby中的过程和数据抽象,ruby,oop,abstraction,Ruby,Oop,Abstraction,我对Ruby不熟悉。我正在学习ruby中的抽象原理。据我所知,过程抽象是对用户隐藏实现细节,或者只是专注于要点而忽略细节 我关心的是如何实施它 1) 是这样简单的函数调用吗 # function to sort array # @params array[Array] to be sort def my_sort(array) return array if array.size <= 1 swapped = false while !swapped swapped

我对Ruby不熟悉。我正在学习ruby中的抽象原理。据我所知,过程抽象是对用户隐藏实现细节,或者只是专注于要点而忽略细节

我关心的是如何实施它

1) 是这样简单的函数调用吗

# function to sort array
# @params array[Array] to be sort

def my_sort(array)
  return array if array.size <= 1

  swapped = false
  while !swapped
    swapped = false
    0.upto(array.size-2) do |i|
      if array[i] > array[i+1]
        array[i], array[i+1] = array[i+1], array[i]
        swapped = true
      end
    end
  end

  array
end
2) 数据抽象与封装有何不同


据我所知,数据抽象只是对其他类隐藏一些成员数据。

您正在从该方法返回一个数组。数据结构是实现细节。如果更改方法中使用的数据结构,则会破坏客户端代码。因此,您的示例不会隐藏实现细节。它不会封装设计决策,从而使客户机的决策与内部实现细节隔离。

数据抽象是大多数面向对象语言的基础,其中类被设计为封装数据,并提供控制数据修改方式的方法(如果有的话),或助手方法来派生该数据的含义

Ruby的数组类是数据抽象的一个例子。它提供了一种管理对象数组的机制,并提供了可以在该数组上执行的操作,而无需关心数组内部的组织方式

arr = [1,3,4,5,2,10]
p arr.class # Prints Array
p arr.sort # Prints [1,2,3,4,5,10]
过程抽象是关于向用户隐藏过程的实现细节。在上面的例子中,您实际上不需要知道内部使用了什么排序算法
sort
方法,只要假设Ruby Core团队中的好人为您选择了一个最好的排序算法,就可以使用它

同时,Ruby可能不知道如何始终比较
数组中的两个项。例如,下面的代码不会运行,因为Ruby不知道如何比较字符串和数字

[1,3,4,5,"a","c","b", 2,10].sort 
#=> `sort': comparison of Fixnum with String failed (ArgumentError)
它允许我们连接到实现中并帮助进行比较,即使底层排序算法保持不变(因为它是从用户抽象出来的)

[1,3,4,5,“a”,“c”,“b”,2,10].排序{i,j}
如果i.class==String和j.class==String
i j
elsif i.class==Fixnum和j.class==Fixnum
i j
其他的
0
结束
}
#=>[1,3,4,5,2,10,“a”,“b”,“c”]
在为自己的问题编写代码时,可以使用过程抽象来确保过程经常将其问题分解为子问题,并使用单独的过程解决每个子问题。这允许以后扩展某些方面(如上面的例子,可以扩展比较-多亏了Ruby
块,这就容易多了)。这是实现这一目标的好方法

“抽象”的定义:处理思想而不是事件的质量

参考这个答案和我的理解,我发现在您的代码中,
my_sort
方法充分证明了
封装的合理性,因为它封装了与任何
一维数组的排序相关的
行为。但是它缺少
抽象
,因为方法
my_sort
知道它将处理的数据类型

如果它不知道/关心通过params传入的数据类型,那么它就有理由进行
抽象。换句话说,它应该对传入的任何对象进行排序,无论它是
Fixnum
String
或其他
可排序数据类型的列表

封装

我们通常使用访问修饰符(
public
private
,…)来区分将暴露给
客户机的数据/行为和将在
内部使用的数据/行为。公共接口(向客户端公开)尽可能不受更改的影响。但是,
private
是可以改变的行为,在任何情况下都不应影响
客户所依赖的代码的预期行为。
此外,我们还将敏感数据/行为分离为私有/受保护,以防止意外修改/误用。这使得客户机不依赖可能频繁更改的代码部分

  • 因此,始终需要将
    核心逻辑
    私有
    范围分开
抽象

例如:
在教堂中,
忏悔者
父亲/牧师
之间有一个
抽象概念
。忏悔者不应该知道牧师的名字或任何细节,反之亦然。无论他/她犯了多大的错误/罪行,任何人都可以坦白并隐藏自己的身份。

谢谢你,旺德。我们是在不知不觉中进行抽象的吗?我想我们是在知情的情况下进行抽象的,这对好的设计是至关重要的。对不起,但我担心的是。假设我做了一个计算阶乘的函数,用户将其作为事实(num)调用。那么我们可以说它是抽象的,是的。因为函数的用户不必担心实现。计算阶乘的逻辑很好地“抽象”了,太棒了!!很好的解释,但是你错过了我的第二个问题。你能回答这个问题吗。
[1,3,4,5,"a","c","b", 2,10].sort 
#=> `sort': comparison of Fixnum with String failed (ArgumentError)
[1,3,4,5,"a","c","b", 2,10].sort { |i,j| 
    if i.class == String and j.class == String
        i <=> j
    elsif i.class == Fixnum and j.class == Fixnum
        i <=> j
    else
        0
    end
}
#=> [1, 3, 4, 5, 2, 10, "a", "b", "c"]