面向对象的核心

面向对象和函数式不是对立的。

面向对象语言的分类

  • 纯面向对象语言:一切都是对象,包括数字、字符串也是对象,如 Python、Ruby、Scala、Smalltalk
  • 完全支持面向对象,也支持过程式,如 Java、C++、C#
  • 本来不支持面向对象,后来加上的,如 PHP、Perl
  • 看起来像面向对象,但没有完全使用面向对象(比如基于原型来模拟面向对象):JavaScript、Lua
  • 其他还有很多种。

设计模式

设计模式指的是对于某个广泛出现的问题提出的适用性广的、可复用的解决方法,也叫套路。
某些面向对象语言内置了一些套路,如单例、事件、工厂等。

对面向对象的批评

  1. 复用性和模块化并没有达到预期目标。
  2. 过分强调模型,而忽略了计算和算法。

Smalltalk

双引号是注释,不要使用。

(1 + 2) * 3
'Hello, world' printNl //'Hello, world'

数组

x := Array new: 20 //将一个数组赋值给x 数组的长度是20,默认会打印出20个nil(也就是null)
x at: 1 //获取x里面的第一个(初始化索引就是从1开始)
x at: 1 put: 99 // x在第一个位置放一个99
(x at: 1) + 1 //在x第一个位置的数加1

Set
使用英文句号断句

x := Set new // 赋值给x一个不能重复的数组
x add: 5. x add: 7. x add: 'foo' // 在x里添加5 7 'foo',打印出Set(5 7 'foo')
x remove: 5 // 从x里移除5
x includes: 7 // x里面是否包含7 false不包含,true包含

有一种简写形式,可以少写几次 x

x add: 5; add: 7; add: 'foo'

打印出x

x 或者 x yourself 或者 x printNl

字典

y := Dictionary new  // Dictionary()
y at: 'One' put: 1 // 在One中添加一个1 Dictionary('One' -> 1)
y at: 'Two' put: 2
y at: 1 put: 'One'
y at: 2 put: 'Two'


y at: 1 //y在1对应的值 'One'
y at: 'Two'
y
y! 用于删除 y 的值
y

面向对象的核心就是对象与对象之间交互。

  1. 对象维护自己的状态和生命周期
  2. 每个对象独立
  3. 对象和对象直接通过消息传递来工作

函数式也可以做成消息传递风格

消息传递风格使用消息传递风格就可以构造 account 对象了,account 对象可以响应 withdraw(取钱)和 deposit(存钱)消息:

let makeAccount = money => {
  let take = (n) => {
    money = money - n
    return money
  }
  let save = (n) => {
    money = money + n
    return money
  }
  let dispatch = (m) => {
    return (
    m === 'take' ? take :
    m === 'save' ? save :
    new Error('unknown request'))
  }
  return dispatch
}

接下来是使用 makeAccount 创造两个 account 对象(其实是过程):

let account1 = makeAccount(100)
account1('take')(70) // 30
account1('save')(50) // 80

函数式代码示例(Pager组件)

function Pager(props) {
  const buttons = Array.apply(null, { length: props.total })
    .map((n, index) => index + 1)
    .filter(n => {
      if (n === 1) {
        return true;
      } else if (n === props.total) {
        return true;
      } else if (Math.abs(n - props.current) <= 2) {
        return true;
      } else {
        return false;
      }
    })
    .reduce((prev, n) => {
      const last = prev[prev.length - 1];
      return prev.concat(n - last > 1 ? [-1, n] : [n]);
    }, [])
    .map(n => (n === -1 ? ... : ));
  return 
{buttons}
; } function App() { return (
); }

在线demo:https://codesandbox.io/s/happy-williams-n80v7

赋值的本质

如果没有赋值,参数和变量只不过就是一个值的名字;
如果有了赋值,参数和变量 就是一个容器,可以保存不同的值。

这带来的问题很多。广泛采用赋值的程序设计叫做『命令式/指令式』程序设计。

命令式程序在遇到『并发』『克隆』等问题时经常很令人头疼。

函数式编程的特点

  1. 数学!(公理化和可证明)
  2. 更加强调程序执行的结果而非执行的过程
  3. 函数是一等公民(函数可以作为参数),高阶函数
  4. 纯函数,拒绝副作用
  5. 不可变数据
  6. 数据即代码,代码即数据
  7. 引用透明

你可能感兴趣的:(面向对象的核心)