参考自Effective Dart,截至2019/06/12

通用原则

类似其他编程语言,有下面两点注意事项:

  • Be consistent, 统一风格
  • Be brief, 保持精简,DRY

最佳实践

指南以下面的关键词开头:

  • ,一定遵守,下面没有前缀的就是以此开头
  • 不要,这么做不是个好主意
  • 推荐,应该遵守,当不遵守时确保有合理理由
  • 避免,和上面相反,除非有足够好的理由,否则不应该这么做
  • 考虑,根据实际情况而定

同时会提到下面这些客体:

  • 库成员,顶级变量、getter、setter、函数
  • 类成员,类变量、getter、setter、函数
  • 成员,库成员或类成员
  • 变量
  • 属性,类中的成员变量、getter、setter,顶级变量、getter、setter

样式

标识符

  • 类名用UpperCamelCase风格
  • 库和文件名用lowercase_with_underscores风格
  • 导入前缀用lowercase_with_underscores风格
    1
    import 'package:javascript_utils/javascript_utils.dart' as js_utils;
  • 其他标识符使用lowerCamelCase风格
  • 推荐使用lowerCamelCase风格命名常量
    • 原因:CAPS_STYLE可读性差/可能会用于final变量/和枚举不搭
  • 把超过2个字母的缩略词当做一般单词来做首字母大写
    • 原因:提高可读性
  • 不要在标识符前加前缀
    • 举例:kTimes

顺序

  • 把”dart:”导入语句放在最前
  • 把”package:”放在相对导入前
  • 推荐把第三方”package:”导入放在其他语句前
  • export语句放在最后
  • 按字母序排序

格式化

  • 使用dartfmt帮你美化
  • 考虑让你的代码更容易美化
  • 避免每行超过80字符
  • 所有控制结构都使用大括号
    • 只有if语句写成1行时可以省略

文档

注释

  • 使用句子的形式表达注释
  • 用单行注释符表达注释

文档注释

  • ///表达文档注释
  • 推荐为公开API书写注释
  • 考虑为私有API书写注释
  • 用一句话为文档注释开头
  • 类似git commit message,第一行后空出一行独立成段
  • 去掉能从上下文直接读出的冗余信息
  • 推荐使用第三人称动词开头表示函数、方法注释
  • 推荐使用名词短语开头表示变量、成员、getter、setter注释
  • 推荐使用名词短语开头表示库、类型注释
  • 考虑在注释中添加示例代码
  • 在注释中用[]方括号引用作用域里的标识符
  • 使用简短平实的语言描述参数、返回值和异常
  • 在注解(annotation)前添加注释

Markdown

Dart允许在comment中使用Markdown格式。

  • 避免滥用markdown
  • 避免使用html格式化文本
  • 推荐使用反引号(```)格式化代码

行文

  • 推荐简洁清晰
  • 避免使用缩写和首字母缩略词
  • 推荐使用“this”而不是“the”来引用实例成员

实践

下面的规则是书写Dart代码时需要知道的指导原则,尤其是维护你类库的人。

  • 出于历史原因,Dart允许通过part of的方式使用库的一部分文件,使用时通过路径而不是变量名引用

    1
    2
    3
    4
    5
    6
    library my_library;
    // good case
    part of "../../my_library.dart";

    // bad case
    part of my_library
  • 不要从库的src文件夹下引用代码

  • 推荐使用相对路径应用库,但是不要跨src文件夹引用

字符串

  • 在长字符串场景下,使用邻接字符串而不是“+”链接
    1
    2
    3
    4
    // good case
    raiseAlarm(
    'ERROR: Parts of the spaceship are on fire. Other '
    'parts are overrun by martians. Unclear which are which.');
  • 推荐使用插值构造字符串
  • 避免在插值中使用多余的大括号(对于简单的变量)

集合

  • 尽可能使用字面量形式定义集合,必要时提供泛型类型即可
    1
    2
    3
    4
    5
    6
    7
    // good case
    var points = [];
    var userMap = {};

    // bad case
    var points = new List();
    var userMap = new Map();
  • 不使用length属性判断集合是否为空,Dart提供了isEmptyisNotEmpty
  • 考虑使用高阶函数来明确表达你的意图
    1
    2
    3
    var aquaticNames = animals
    .where((animal) => animal.isAquatic)
    .map((animal) => animal.name);
  • 避免Iterable.forEach()中使用函数声明,Dart里的for-in循环可以很好完成该工作,当然函数本身已经定义好除外。
    1
    2
    3
    4
    5
    // good case
    for (var person in people) {
    ...
    }
    people.forEach(print);
  • 使用iterable.toList替代List.from,只在改变list类型时使用List.from
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    // Creates a List<int>:
    var iterable = [1, 2, 3];

    // Prints "List<int>":
    print(iterable.toList().runtimeType);

    // Prints "List<dynamic>":
    print(List.from(iterable).runtimeType);

    // Use it with a type
    var numbers = [1, 2.3, 4]; // List<num>.
    numbers.removeAt(1); // Now it only contains integers.
    var ints = List<int>.from(numbers);
  • 使用高级的whereType方法从collection中过滤出特定类型元素
    1
    2
    var objects = [1, "a", 2, "b", 3];
    var ints = objects.whereType<int>();
  • 有类似用法时,不使用cast()方法
    1
    2
    3
    4
    5
    6
    var stuff = <dynamic>[1, 2];

    // Good case
    var ints = List<int>.from(stuff);
    // Bad case
    var ints = stuff.toList().cast<int>();
  • 避免使用cast()方法,用该方法可能更慢且更有风险,通常情况下有下面一些备选方案
    • 创建有正确类型的list
    • 使用每个集合元素时进行casting操作
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      // Good case
      void printEvens(List<Object> objects) {
      // We happen to know the list only contains ints.
      for (var n in objects) {
      if ((n as int).isEven) print(n);
      }
      }

      // Bad case
      void printEvens(List<Object> objects) {
      // We happen to know the list only contains ints.
      for (var n in objects.cast<int>()) {
      if (n.isEven) print(n);
      }
      }
    • 真正想要强制类型转换时,使用附加类型的List.from

函数

  • 使用函数声明形式命名有名函数(不要使用lambda表达式)
  • 当有有名函数可以完成任务时,不要创建lambda表达式
    1
    2
    3
    4
    5
    6
    7
    // Good case
    names.forEach(print);

    // Bad case
    names.forEach((name) {
    print(name);
    });

参数

  • 使用=分隔入参和它的默认值
  • 不要显式地使用null作为默认值(直接不指定即可)
    1
    2
    3
    void error([String message]) {
    stderr.write(message ?? '\n');
    }

变量

  • 不要显式地使用null初始化变量(语言保证了行为可靠性,不需要再显式设置成null)
  • 不要存储computed value(即可以推算出的值) ,减少冗余信息,保证数据唯一可信源,使用getter和setter去动态推导出它们
  • 考虑忽略局部变量的类型,Dart有强大的静态分析工具帮你推断类型。

成员

  • 不要创建没必要的getter和setter
  • 推荐使用final限定只读属性
  • 考虑使用=>实现只有单一返回语句的函数,对于多行语句建议还是老老实实使用花括号
    1
    2
    3
    get width => right - left;
    bool ready(num time) => minTime == null || minTime <= time;
    containsValue(String value) => getValues().contains(value);
  • 不要使用this.访问成员,除非遇到变量冲突
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    // Good case
    class Box {
    var value;

    void clear() {
    update(null);
    }

    void update(value) {
    this.value = value;
    }
    }

    // Bad case
    class Box {
    var value;

    void clear() {
    this.update(null);
    }

    void update(value) {
    this.value = value;
    }
    }
  • 尽可能地在定义变量时初始化该值

构造函数

  • 尽可能使用更简洁的初始化形式
    1
    2
    3
    4
    class Point {
    num x, y;
    Point(this.x, this.y);
    }
  • 不要在初始化形式中定义类型
  • 使用;代替{}表示空方法
    1
    2
    3
    4
    class Point {
    int x, y;
    Point(this.x, this.y);
    }
  • 不要使用可选的new来返回一个对象
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Widget build(BuildContext context) {
    return Row(
    children: [
    RaisedButton(
    child: Text('Increment'),
    ),
    Text('Click!'),
    ],
    );
    }
  • 不要无谓地使用const(基本上const可能出现在所有你能使用new的地方),因为有些语境已经隐式包含了const语义
    • 字面量集合
    • const构造函数调用
    • metadata注解
    • switch的每一个case

异常处理

  • 不要在on以外的语句中丢弃错误,因为在没有on限定时,catch会捕获所有异常
  • 要只在编程错误时抛出Error的异常
  • 不要显式地捕获Error及其子类
  • 使用rethrow重新抛出异常

异步

  • 推荐使用asyncawait提升你的异步代码可读性
  • 只在必要的时候使用async
    • 代码块中使用了await
    • 希望返回一个Future
    • 希望更方便地处理异步中出现的Error
    • 异步事件发生具有先后顺序
  • 考虑使用高阶函数处理stream
  • 避免直接使用Completer
  • Future<T>而不是T判断FutureOr<T>的具体类型

API设计

命名

  • 使用一致的术语
  • 避免缩写,只使用广为人知的缩写
  • 推荐把描述中心词放在最后
  • 考虑尽量让代码看起来像普通的句子
  • 推荐使用名词短语命名非布尔类型的成员或变量
  • 推荐使用非命令式短语命名布尔类型成员或变量
    • 比如配合be动词的不同时态,isEnabled, hasShown
    • 配合助动词,比如hasChildren, canSave
  • 有可能的情况下,考虑省去上一种情况里的动词
  • 推荐使用正向含义的布尔类型变量/方法名
  • 推荐使用命令式动词命名带有副作用的函数和方法
  • 考虑使用名词短语或非命令式动词命名返回数据为主要功能的方法或函数
    1
    2
    list.elementAt(3)
    string.codeUnitAt(4)
  • 考虑使用命令式动词表示你需要对方法所做工作有所关心
  • 避免使用get开头的命名,它通常能用getter代替
  • 推荐使用to___()来命名类型转换
  • 推荐使用as___()来命名类型快照
  • 避免在命名中使用方法、函数的入参
  • 使用助记符命名类型参数
    • E代表集合元素
    • KV代表key和value
    • R代表return type
    • T, SU命名单一通用且上下文表意清晰的泛型
    • 除上面情况外,可以使用完整词汇作为泛型类型名

下划线开头的成员表示成员是私有的,这个特性是内置在Dart语言中的。

  • 推荐使用私有声明,未用_开头的库中的公开声明、顶级定义表示其他库可以访问这些成员,同时也会受到库实现契约的约束。
  • 考虑在同一个库内定义多个类,这样便于在类之间共享私有变量

Dart是纯OOP的语言,它的所有对象都是类实例。当然不像Java,Dart也允许你定义顶级的变量、函数…

  • 避免定义一个函数就可以实现的只有一个实现方法的抽象类
    1
    2
    3
    4
    5
    typedef Predicate<E> = bool Function(E element);

    abstract class Predicate<E> {
    bool test(E element);
    }
  • 避免定义只有静态成员的类,可以使用顶级变量、函数更方便地实现等价效果。当然,如果变量属于一个组,可以这么实现
  • 避免不必要地定义子类
  • 避免实现一个不作为接口的类
  • 避免mixin不设计用作mixin的类
  • 在你的类支持拓展时,定义好文档
  • 在你的类作为接口存在时,定义好文档
  • 在你的类作为mixin存在时,定义好文档

构造函数

  • 考虑在类支持的情况下,让构造函数成为const

成员

  • 考虑尽可能地把成员变量和顶级变量定义为final类型
  • 使用setter和getter定义computed value
  • 不要使用没有getter的setter
  • 避免在返回bool,double,int,num的方法里返回null
  • 避免在方法中返回this,只为了串联调用函数

类型

Dart中的类型可以帮助使用者理解你API中的静态类型设计,它分两种:类型注解和类型参数。前一种放在变量名前注解变量类型,后一种作为泛型参数传入。

1
2
3
4
5
6
bool isEmpty(String parameter) {
bool result = parameter.length == 0;
return result;
}

List<int> ints = [1, 2];

在未指定类型时,Dart会从上下文自动推断或者使用缺省的dynamic类型。

简言之,Dart提供了强大的类型推导简化了你声明类型的负担,但同时不声明类型会降低API的可读性,下面一些guideline帮你在两点间找到一个平衡。

  • 推荐对于类型表意不清晰的public属性和顶级变量使用类型注解
    1
    2
    3
    Future<bool> install(PackageId id, String destination) => ...

    const screenWidth = 640; // Inferred as int.
  • 考虑对于类型表意不清晰的private属性添加类型注解
  • 避免为局部变量添加类型注解,如果你需要静态类型提供的便利,可以借助is限制变量类型
  • 避免在方法表达式上使用类型,考虑到方法表达式通常作为方法入参,类型可以自动推断,不需要类型注解
  • 避免冗余的泛型和类型注解
    1
    2
    3
    4
    5
    // Good case
    Set<String> things = Set();

    // Bad case
    Set<String> things = Set<String>();
  • 在不希望使用Dart推断的类型时,使用类型注解
  • 推荐使用显示的dynamic代替Dart推断失败回退的dynamic
  • 推荐在Function类型注解中添加函数类型签名
  • 不要为setter指定返回值
  • 使用新式的typeof判断类型
    1
    typedef Comparison<T> = int Function(T, T);
  • 使用Object代替dynamic表示可以接受任何对象
  • 使用Future<void>作为无返回值的异步函数返回类型
  • 不使用FutureOr<T>作为返回值

参数

  • 避免位置参数作为可选布尔参数,这样可读性比较差
    1
    2
    3
    4
    5
    6
    7
    // Bad case
    new Task(true);
    new Task(false);
    new ListBox(false, true, true);
    new Button(false);

    // Good case
  • 避免将用户想忽略的参数放在位置可选参数的前列
  • 避免使用强制的无意义的参数
    1
    2
    // Bad case
    string.substring(start, null)
  • 使用左闭右开区间表示两个参数代表的范围

相同判断

  • 覆写==的同时覆写hashCode,默认的哈希函数实现了恒等式哈希。任何两个相等的两个对象必须具有相同的哈希值
  • ==需要遵循数学的相等规则
    • 自反,a == a
    • 对称,a == b => b == a
    • 传递,a == b && b == c => a == c
  • 避免为可变对象自定义相等函数,hashCode函数会增加你的工作量
  • 不要在自定义==中判断null,Dart也已经替你做了这部分工作

入门

1
2
3
4
5
6
7
8
9
10
// 定义个方法。
printNumber(num aNumber) {
print('The number is $aNumber.'); // 在控制台打印内容。
}

// 这是程序执行的入口。
main() {
var number = 42; // 定义并初始化一个变量。
printNumber(number); // 调用一个方法。
}
  • 注释:///* ... */,同其他主流语言
  • 类型:num、String、int、bool等
  • 字面量:42,’Hello world!’
  • 函数:类似print()的形式
  • 字符串插值
  • 入口方法:main

基本理念

  • 所有可以用变量引用的都是对象,每个对象都是一个类的实例,例如数字、方法、null,所有对象都继承Object类
  • Dart是强类型语言。但是不强制使用类型标注,因为它可以通过推导得到变量类型。在你明确不希望有类型时,使用dynamic关键字表示动态类型
  • Dart支持泛型,比如List<int>
  • Dart支持顶级方法main(),支持类的静态方法、实例方法,也可以在函数内使用函数
  • 类似地,Dart支持全局变量、局部变量和在类中定义的成员变量
  • Dart没有public、protected、private的区分,如果标识符以_开头,那么该标识符就是私有的
  • Dart的变量名只能以下划线和字母开头,后跟字符或数字
  • Dart区分语句块和表达式,只有表达式有值。

关键字

分为三类:

  • 对于只在特定上下文环境下生效的上下文关键字,可以用作标识符
  • 对于内置标识符,为了便于移植JavaScript代码到Dart,这些关键字不可用作类或类型名或import的前缀
  • 其他关键字为保留字

变量

1
2
3
4
var name = 'Dart';

String name = 'Dart';
Dynamic name = 'Dart';

根据基本理念,变量都是存储值的引用。使用var修饰时,变量类型会自动推导;也可以显示声明变量类型,或者使用dynamic关键字表示变量可能有多种类型。

任何没有初始化的变量默认值都为null。

常量使用finalconst(实例变量只能用final)。

1
2
3
4
5
6
7
8
final name = 'foo';
final String title = 'FE';

const foo = 10000;
const double percent = 0.314;

final bar = const[];
const baz = []; // 和上面一个效果
  • final变量只能赋值一次,const变量是编译时常量。
  • const除了用来定义不变量,还可以用来创建不变的值,以及定义创建常量的构造函数。在这么用时可以省略构造过程,像上面的baz变量一样

内置类型

  • numbers
  • strings
  • booleans
  • lists (也被称之为 arrays)
  • maps
  • runes (用于在字符串中表示 Unicode 字符)
  • symbols

再次重申,Dart中变量都是一个对象,所以你都可以使用构造函数来初始化。

Number

intdouble两种类型。提供了原生操作符和abs()等常用函数,整数和浮点数的字面量初始化类似js。

字符串和数字互转:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// String -> int
var one = int.parse('1');
assert(one == 1);

// String -> double
var onePointOne = double.parse('1.1');
assert(onePointOne == 1.1);

// int -> String
String oneAsString = 1.toString();
assert(oneAsString == '1');

// double -> String
String piAsString = 3.14159.toStringAsFixed(2);
assert(piAsString == '3.14');

String

Dart的字符串是UTF-16编码的字符序列。可以使用单引号或双引号创建。字符串中用${expr}的语法使用表达式,**如果表达式是一个标识符,可以省去{}**,对{}内的表达式,Dart使用toString()方法转成字符串使用。

使用'''"""表示多行字符串。使用r''表示纯字符串。

Boolean

布尔类型有两个字面量值,truefalse。和JavaScript不同的是,在if语句等使用bool类型的地方,只有true被认为是true,其余所有值都是false。这也是为了避免JavaScript中判断true、false时坑爹的地方。

1
2
3
4
5
6
7
if (1) {
print('JS prints this line.');
} else {
print('Dart in production mode prints this line.');
// However, in checked mode, if (1) throws an
// exception because 1 is not boolean.
}

List

List的字面量写法和JavaScript一样。Dart会做类型推导,在元素类型不一致时报错。你可以使用const语句定义一个不变的List对象。

1
2
const list = [1, 2, 3];
var list = const [1, 2, 3];

2.3后,Dart支持...解构操作符,以及对空列表兼容的...?。同时支持collection if和collection for语法。

1
2
3
4
5
6
7
8
9
10
11
var nav = [
'Home',
'Furniture',
'Plants',
if (promoActive) 'Outlet'
];
var listOfInts = [1, 2, 3];
var listOfStrings = [
'#0',
for (var i in listOfInts) '#$i'
];

Set

2.2版本后支持

一组元素唯一的无序列表。字面量写法类似数学中集合的定义方法。

1
var halogens = {'fluorine', 'chlorine', 'bromine', 'iodine', 'astatine'};

也可以使用构造函数的方式创建。

1
2
3
var elements = <String>{};
elements.add('fluorine');
elements.addAll(halogens);

类似List,2.3之后有......?的语法支持。

Map

表达键值对数据,每个键只出现一次,且可以是任意类型。类似Set,可以使用字面量和构造函数两种方式构造。使用字面量时,Dart会做类型推导。

Map的设置和JavaScript类似,另外类似List,2.3之后有......?的语法支持。

Rune

Dart用Rune类型表示UTF-32的字符,如emoji等。

Symbol

用来代表Dart中声明的操作符或标识符,可以在标识符前添加#获取标识符的Symbol对象。

方法

类似JavaScript,Dart中的Function也是对象并具有Function类型。推荐使用显式类型声明方法。

1
2
3
bool isNoble(int atomicNumber) {
return _nobleGases[atomicNumber] != null;
}

Dart支持箭头函数。

可选参数

可选参数分两种:命名参数、位置参数。

命名参数使用param: value指定,在调用时使用{param1, param2}的形式传递参数。支持在参数前添加@required表示参数必选。

位置参数使用[]包裹方法参数,使用时不传参数即可。

1
2
3
4
5
6
7
8
9
enableFlags(bold: true, hidden: false);
enableFlags({bool bold, bool hidden}) {
// ...
}

String say(String from, String msg, [String device]) {
// ...
}
assert(say('Bob', 'Howdy') == 'Bob says Howdy');

定义方法时,可以使用=定义可选参数的默认值。否则默认值为null。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
String say(String from, String msg,
[String device = 'carrier pigeon', String mood]) {
var result = '$from says $msg';
if (device != null) {
result = '$result with a $device';
}
if (mood != null) {
result = '$result (in a $mood mood)';
}
return result;
}

assert(say('Bob', 'Howdy') ==
'Bob says Howdy with a carrier pigeon');

main函数

每个应用都需要有顶级的main()函数作为入口,返回值void类型,并且有可选的List<String>参数(用于解析命令行输入的参数数据)。如

1
2
3
4
5
void main() {
querySelector("#sample_text_id")
..text = "Click me!"
..onClick.listen(reverseText);
}

上面的..语法为级联调用,表示在一个对象上执行多个操作。

第一公民

类似JavaScript,Dart中Function可以作为参数、返回值、变量、对象使用。同样也有匿名函数可以使用,区别是箭头后是语句块时,不使用箭头,只在之后是表达式时使用箭头。

作用域与闭包

Dart是静态作用域,即变量的作用域在写代码时就确定了,作用域层级即大括号的层级。

类似JavaScript,Dart的闭包意味着方法可以封闭其作用域内的变量。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/// Returns a function that adds [addBy] to the
/// function's argument.
Function makeAdder(num addBy) {
return (num i) => addBy + i;
}

void main() {
// Create a function that adds 2.
var add2 = makeAdder(2);

// Create a function that adds 4.
var add4 = makeAdder(4);

assert(add2(3) == 5);
assert(add4(3) == 7);
}

返回值

所有函数必须返回一个值,否则默认return null

操作符

  • ~/返回取整截断的商
  • 使用==判断相等性
    • 会调用左侧对象的==方法,和后面的对象对比
  • 类型转换:
    • as,类型转换,类似typescript中的as
    • is 判断对象是否是指定类型
    • is! 判断对象是否不是指定类型
  • ??=在value不是null时赋值给变量
  • expr1 ?? expr2表示如果expr1是非null则返回其值,否则执行expr2并返回
  • .. 级联操作符,表示在一个对象上连续调用多个函数以及访问成员变量,可以嵌套
  • ?..类似,但是在左侧操作对象为null时返回null
    1
    2
    3
    4
    5
    6
    7
    8
    final addressBook = (new AddressBookBuilder()
    ..name = 'jenny'
    ..email = 'jenny@example.com'
    ..phone = (new PhoneNumberBuilder()
    ..number = '415-555-0100'
    ..label = 'home')
    .build())
    .build();

流程控制

  • for循环中,Dart会自动捕获当时的index索引值,避免JavaScript中问题。对interable的对象可以使用forEach()方法遍历,对List、Set还支持for-in形式的遍历
  • switch中的每个case(除了空case)都必须有break
  • assert在检查模式下会被跳过

异常

和JavaScript中的异常类似。

不一样的是,可以使用oncatch捕获异常,可以通过rethrow在其中重新抛出异常。

  • 构造方式类似ES6中引入JavaScript Class。
  • 用成员方式声明的类变量在定义时初始化,也就是在构造函数前
  • 可以使用Object的runtimeType属性来判断实例的类型
  • 使用const关键字结合构造函数可以构造出不可变的对象实例

构造函数

使用和类名同名的方法作为构造函数(或者使用命名构造函数)。因为把构造函数参数赋值给实例变量的场景太常见了,Dart提供了下面的语法糖。

1
2
3
4
5
6
7
8
class Point {
num x;
num y;

// Syntactic sugar for setting x and y
// before the constructor body runs.
Point(this.x, this.y);
}

可以使用命名构造函数实现多个构造函数。

1
2
3
4
5
6
7
8
9
10
11
12
class Point {
num x;
num y;

Point(this.x, this.y);

// Named constructor
Point.fromJson(Map json) {
x = json['x'];
y = json['y'];
}
}

子类不会从父类继承构造函数,在未定义构造函数时,会有一个默认构造函数,这个函数没有参数,且会调起父类的没有参数的构造函数。

在有初始化参数列表(initializer list)的情况下,初始化参数列表在父类构造函数前执行。

  1. 初始化参数列表
  2. 父类无参构造函数
  3. 子类无参构造函数

父类没有无参构造函数时,需要手动调用父类的其他构造函数。

初始化列表

在执行父类构造函数前,可以初始化实例参数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Point {
num x;
num y;

Point(this.x, this.y);

// Initializer list sets instance variables before
// the constructor body runs.
Point.fromJson(Map jsonMap)
: x = jsonMap['x'],
y = jsonMap['y'] {
print('In Point.fromJson(): ($x, $y)');
}
}

在冒号右边用逗号隔开初始化表达式。注意:等号右边无法访问this

重定向构造函数

重定向构造函数没有代码,在构造函数声明后,用冒号调用其他构造函数

1
2
3
4
5
6
7
8
9
10
class Point {
num x;
num y;

// The main constructor for this class.
Point(this.x, this.y);

// Delegates to the main constructor.
Point.alongXAxis(num x) : this(x, 0);
}

常量构造函数

如果类支持提供状态不变的对象,需要定义一个const构造函数,且所有类变量都要是final

1
2
3
4
5
6
7
class ImmutablePoint {
final num x;
final num y;
const ImmutablePoint(this.x, this.y);
static final ImmutablePoint origin =
const ImmutablePoint(0, 0);
}

工厂构造函数

当你的构造函数不需要返回新对象,而从其他地方获取时(如缓存),使用工厂构造函数。**工厂构造函数内无法访问this**。调用时方式和普通构造函数等同。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Logger {
final String name;
bool mute = false;

// _cache is library-private, thanks to the _ in front
// of its name.
static final Map<String, Logger> _cache =
<String, Logger>{};

factory Logger(String name) {
if (_cache.containsKey(name)) {
return _cache[name];
} else {
final logger = new Logger._internal(name);
_cache[name] = logger;
return logger;
}
}

Logger._internal(this.name);
}

var logger = new Logger('UI');

方法

类方法可以访问this,另外对于类对象的每个属性都有隐含的getter和setter(final除外)。也可以显式使用getset定义getter和setter的行为。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Rectangle {
num left;
num top;
num width;
num height;

Rectangle(this.left, this.top, this.width, this.height);

// Define two calculated properties: right and bottom.
num get right => left + width;
set right(num value) => left = value - width;
num get bottom => top + height;
set bottom(num value) => top = value - height;
}
  • Dart使用extends继承,用super指代父类,用@overide注解重载操作。
  • Dart中有抽象类/抽象方法,设计和使用类似Java的抽象类/抽象方法。如果你希望抽象类可实例化,可以定义一个工厂工造函数。
  • 每个类都隐式的定义了一个包含所有实例成员的接口,通过使用implement实现若干其他类的API(不包括构造函数)
  • 可以重载一些操作符,如+, -, [], >>等,实现在特定类上的特定表现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Vector {
final int x;
final int y;
const Vector(this.x, this.y);

/// Overrides + (a + b).
Vector operator +(Vector v) {
return new Vector(x + v.x, y + v.y);
}

/// Overrides - (a - b).
Vector operator -(Vector v) {
return new Vector(x - v.x, y - v.y);
}
}

有意思的是,Dart提供noSuchMethod()方法,在访问不存在的类实例或方法时被调用。如果没有填写,默认使用Object的同名方法。

1
2
3
4
5
6
7
@proxy
class A {
void noSuchMethod(Invocation inv) {
print('You tried to use a non-existent member: ' +
'${inv.memberName}');
}
}

枚举

枚举是特殊的类,使用enum关键字定义。每个枚举值都有index属性的getter函数,枚举的values常量可以返回所有枚举值。

1
2
3
4
enum Color { red, green, blue }
assert(Color.red.index == 0);
List<Color> colors = Color.values;
assert(colors[2] == Color.blue);

mixin

Dart中提供了多类继承中重用类代码的mixin,用with结合mixin类实现,这种类没有构造函数。除非你想像正常类一样使用mixin,否则使用mixin关键字。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
mixin Musical {
bool canPlayPiano = false;
bool canCompose = false;
bool canConduct = false;

void entertainMe() {
if (canPlayPiano) {
print('Playing piano');
} else if (canConduct) {
print('Waving hands');
} else {
print('Humming to self');
}
}
}

当限制mixin只在特定类中使用时,结合on让mixin也能调用父类方法。

1
2
3
mixin MusicalPerformer on Musician {
// ···
}

类变量、函数

使用static前缀修饰,表示类级别的变量、函数。类变量只在第一次使用时初始化。静态方法无法访问this。

泛型

使用泛型的两个动机:

  • 有助于IDE、环境、同事帮你定位问题和代码自动生成
  • 减少重复代码

List和Map的泛型定义类似C++风格。

1
2
3
4
5
6
7
8
9
10
var names = <String>['Seth', 'Kathy', 'Lars'];
var pages = <String, String>{
'index.html': 'Homepage',
'robots.txt': 'Hints for web robots',
'humans.txt': 'We are people, not machines'
};

var names = new List<String>();
var views = new Map<int, View>();
print(names is List<String>); // true

在泛型中使用extends可以限制泛型的具体类型。在1.21之后,Dart支持泛型函数。

1
2
3
4
5
6
T first<T>(List<T> ts) {
// ...Do some initial work or error checking, then...
T tmp ?= ts[0];
// ...Do some additional checking or processing...
return tmp;
}

包管理

使用importlibrary引入和导出模块。_开头的标识符只在库内部可见。

1
2
3
4
5
6
7
import 'dart:html';
import 'dart:io';
import 'package:mylib/mylib.dart';
import 'package:utils/utils.dart';

import 'package:lib2/lib2.dart' as lib2; // 指定库前缀,避免重名
import 'package:lib1/lib1.dart' show foo; // 部分导入

dart:开头代表内置库,package:开头代表外部库。外部库使用pub包管理器管理。

懒加载库

懒加载即在使用时再加载库,如优化app启动时间,加载很可能用不到的功能。

加载时使用deferred as导入,使用loadLibrary()方法加载。

1
2
3
4
5
6
import 'package:deferred/hello.dart' deferred as hello;

greet() async {
await hello.loadLibrary();
hello.printGreeting();
}

异步支持

Dart中返回FutureStream的方法都是异步的,意味着设置好耗时操作(I/O)后就返回。类似ES7中的awaitasync,你也可以像组织同步代码一样组织你的异步代码。

Dart中声明异步方法是在函数名后加入async,这类方法返回一个Future对象,了解JS中Promise的同学可以很快理解Future是做什么的。

1
2
3
4
5
6
7
8
checkVersion() async {
var version = await lookUpVersion();
if (version == expectedVersion) {
// Do something.
} else {
// Do something else.
}
}

在返回值是Stream时,使用await for的形式接收Stream中的数据。另外别忘了用async修饰外界函数。

1
2
3
4
5
6
7
Future main() async {
// ...
await for (var request in requestServer) {
handleRequest(request);
}
// ...
}

生成器函数

惰性生产数据,类似ES6中的function*。Dart提供两种类型:

  • 同步:返回Iterator
  • 异步:返回Stream
1
2
3
4
5
6
7
8
9
10
Iterable<int> naturalsDownFrom(int n) sync* {
if (n > 0) {
yield n;
yield* naturalsDownFrom(n - 1);
}
}
Stream<int> asynchronousNaturalsTo(int n) async* {
int k = 0;
while (k < n) yield k++;
}

可调用的类

类中实现了call()方法时,类实例可以当做方法调用。

1
2
3
4
5
class WannabeFunction {
call(int a, int b) => a + b;
}
var wf = new WannabeFunction();
wf(3, 4); // 7

类型别名

类似typescript中的interface定义,Dart可以借助typedef进行一些更复杂的类型判断。typedef只是类型别名的一种说法。

1
2
3
4
5
6
7
typedef int Compare(int a, int b);

int sort(int a, int b) => a - b;

main() {
assert(sort is Compare); // True!
}

元数据

使用元数据给代码添加额外信息,也能便于文档自动生成。

  • @deprecated
  • @override
  • @proxy

你还可以自定义自己的元数据注解:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
library todo;

class todo {
final String who;
final String what;

const todo(this.who, this.what);
}

// another file
import 'todo.dart';

@todo('seth', 'make this do something')
void doSomething() {
print('do something');
}

注释

  • 单行,//
  • 多行,/**/
  • 文档注释, ///开头,或/**开头,*/结束

遵守规范的注释风格会有助于文档自动生成。

《程序员修炼之道》这个书名实际上不如原版《The Pragmatic Programmer: From Journeyman to Master》来得更清晰明了。此书第一版写于1999年,我看的是11年的版本,但还是透流露着不少世纪初的观念和视野。除开一部分观点认识的过时,书中绝大多数观点都四溢着国外互联网行业的工作风格和流程,和国内凶猛生长、一把梭就是干的风格各有不同,甚至我感觉国内IT,尤其是互联网企业里的工作流更加讲求实效。尽管和读之前的预期不大一样,里面许多经验还是很有借鉴意义,比如正交性、不要依赖巧合等等。

书中内容在项目管理、编程哲学、以及编程过程的各个方面都有涉及,在这些方面上更加深入的探讨,书的最后也推荐了继续阅读的材料。下面就各章节的关键观点加以整理。

关于本书的读法:

  • 能不能让正确原则指导正确的行动本身,其实就是区分是否是高手的一个显著标志
  • 要能内化书中提到的各个小提示,不实践的话,是不会有太大收获的
  • 思考,你的工作,多思考

实效哲学

  • 对你的源码负责
  • 不要容忍破窗,它们会增大你软件的熵(这个也是要结合实际情况看的)
  • 记住大图景,注意方向是否有误,不要光低头做事
  • 知道在何时打住,你不可能做到完美
  • 定期为你的知识资产投资,就像经济投资一样
    • 定期投资
    • 多元化
    • 管理风险,不要把所有技术放在一个篮子里
    • 低买高卖,能看清形势
  • 为此,你需要
    • 每年至少学习一种新语言
    • 每季度阅读一本技术书籍
    • 也要阅读非技术书籍
  • 批判地思考你读到和听到的
  • 如何表达自己很重要,这会增加你的影响力
    • 你想让谁知道
    • 你想让他们知道什么
    • 他们是否感兴趣
    • 他们需要知道细节么
    • 如何促使他们与你交流

实效途径

  • DRY,不要重复自己
    • 强加的重复 => 使用自动生成,减少是信息冗知识
    • 无意的重复 => 优良的设计
    • 无耐心的重复 => 考虑长远
    • 开发者间的重复 => 加强组内交流,制定代码规范,制造更容易复用的环境
  • 减少无关事物的影响,非正交 => 次级效应 => 补偿行为 => 经验依赖
    • 好处:提高生产率(促进复用)、降低风险(风险隔离,易测试)
    • 分层设计、抽象和接口约定
    • 避免使用全局变量
    • 考虑使用库的代码侵入性
    • 文档和认同正交性
  • 不存在最终决策,当需求变动频繁的时候,不仅要思考程序架构如何适应这种变动,也要反思是否是设计者没想清楚到底要做什么
  • 使用曳光弹找到目标,即MVP + 快速迭代 + 即时的反馈
    • 逐步逼近,摸着石头过河
    • 曳光弹模式永远包含着一个可用的软件版本
  • 原型和便笺,使用原型去表达和快速验证项目的可行性
  • 靠近问题领域编程
    • 使用DSL(Domain Specified Language)
  • 估算,以避免意外,主要用来估计工期、分析风险
    • 适当地降低估算速度,慎重思考隐藏的风险

基本工具

工具成为双手和大脑的延伸,优秀的工具可以放大你的才干。

  • 纯文本以其自解释能力几乎可以永久保存,XML、JSON就是利用此成为通用的数据表现形式
  • 利用shell的力量,它是自动化任务避不开的工具
  • 要能烂熟地使用你的编辑器要使用高级的编辑器,由于你的所有开发工作都建立在它上面,做好这两点可以节省你大量时间
    • 反思一下,在用你的编辑器时,你有遇到过到比较繁琐的操作吗?
    • 是因为你不会高级使用方式,还是编辑器本身不支持?
  • 总是使用源码控制(这一点早已成为共识)
  • 调试,debug
    • 通常认为匪夷所思的bug,都来自健忘、自大和愚蠢
    • QA角色的重要性之一:帮助复现、找到规律性
    • 橡皮鸭调试法
    • 二分查找法
    • 如果bug来自某人的错误假设,那么需要清除团队其他人的相同误解
  • 学习一种文本操纵语言或工具,例如awk,sed,处理数据和结果时一定能用上
  • 编写代码生成器
    • 开发者手动触发,如模板代码
    • 程序自动出发,如scheme to idl,idl to code

偏执编程

  • 通过合约设计,约定好接口,合作方基于接口开发
    • 强类型语言更容易实现这一点
  • 早崩溃,这在需要编译的软件开发上比较科学,对于web应用来说却不是这样
  • 使用断言确保某事不会发生,减少预设条件代理的隐藏bug
    • 不要滥用断言
  • 只在异常处用异常
  • 一定记住释放请求的资源,如内存、句柄等,可以通过封装统一的资源类实现自动的资源释放

时间的魔力

  • 德墨忒尔法则,使模块间的依赖减少到最小
    • 物理解耦
  • 要配置不要hardcode,使用元数据动态描述你的程序
    • 抽象放进代码,细节放进元数据
  • 时间耦合:考虑并发和事件的发生顺序
    • 在异步代码中,总考虑并发
  • 一些GUI的设计模式
    • 发布订阅
    • MVC
  • 基于规则/规则集的黑板系统
    • 黑板给出统一接口
    • 耦合方通过调用黑板接口避免耦合
    • 黑板通过规则给出输出

编码时

  • 不要靠巧合编程
    • 改动要有文档沉淀
    • 只依靠文档中记录的行为
    • 把你的假设记入文档
  • 在大数据量时,考虑算法数量级
    • 兼顾效率和可读性
  • 早重构,常重构,代码是业务设计的近似同构体,常重构才能保证代码完美贴合需求设计
    • 重构和功能开发分开进行
    • 重构一定要有测试
  • 优秀的代码不是看新增了多少行,而是看删除了多少行
  • 编写易于测试的代码
    • 测试你的软件,否则你的用户会代你做测试

项目开始前

完美,不是在没有什么需要增加,而是在没有什么需要去掉的时候达到的。

  • 去挖掘需求,思考用户做特定事情的原因,和如何去做的方式,让需求成为一种一般性的陈述
    • 制作需求文档时的一大危险是太过具体,好的需求文档会保持抽象
    • 经常性复盘
    • 鼓励文档分享和交流
  • 巧妙解决看似不能解决的难题,关键要找到真正的约束,去思考
    • 有更容易的方法么
    • 你是在解决真正的问题,还是被外围的技术问题转移了注意力
    • 这件事为什么是一个问题
    • 是什么让它难以解决
    • 它必须这么做么
    • 它必须完成么
  • 准备好再开始,但不要让它成为你懈怠的借口
  • 不要成为方法学的奴隶

实效项目

  • 团队建设
    • 不留破窗户(考验leader的管理能力)
    • 经常性的复盘和例会
    • 减少团队成员分工的冗余
    • 自动化项目流程 => 效率工程团队开发内部工具
    • 制造context,给成员足够空间
  • 不要使用手动流程,它不可控且难以复制
    • shell、crontab
    • CI和自动化持续集成
    • 代码生成
    • 自动化测试
    • 代码review和源码版本控制流程
  • 常测试,早测试,自动化测试
    • 单元测试/集成测试/压力测试/回归测试
    • 测试状态覆盖,而不是代码覆盖,代码覆盖率提供的意义有限
  • 关于如何生产文本
    • 所有文档都是代码的反映
    • 源码注释应该去把项目里那些难以描述、容易忘记、不能记录在其他地方的东西记载下来
    • 比无意义的名称更糟糕的是有误导性的名称
    • 除非有程序或人工维护,否则任何形式的文档都只是快照
  • 温和地超出用户期望,如
    • 友好的新手指引
    • 快捷键
    • 自动化安装
  • 自豪地为你的作品签名

更多资源

  • 《人月神话》
  • 《Unix编程艺术》
  • 《Effective C++》
  • 《集市与大教堂》

–END–

正文:《经济学原理》 - 微观经济学原理笔记

导言

经济学十大原理

  • 稀缺性:社会资源的有限性
  • 经济学:研究社会如何管理自己的稀缺资源
  • 机会成本:为得到某种东西必须放弃的东西
  • 理性人:系统有目的地尽最大努力实现其目标的人
  • 边际变动:对行动计划的增量调整
  • 激励:引起一个人做出某种行为的某种东西
  • 市场经济:在许多企业和家庭在物品与服务市场上交互交易时。通过他们的分散决策配置资源的经济
  • 产权:个人拥有并控制稀缺资源的能力认证
  • 生产率:单位劳动投入所生产的物品与服务数量
  • 通货膨胀:经济中物价总水平的上升
  • 经济周期:就业和生产等禁忌活动的波动

像经济学家一样思考

  • 循环流量图:一个说明货币如何通过市场在家庭和企业间流动的经济模型
  • 生产可能性边界:生产要素和生产技术固定时,一个经济所能生产的数目组合的图形
  • 微观经济学:研究家庭和企业如何做出决策,以及它们如何在市场上相互交易
  • 宏观经济学:研究整体经济现象
  • 实证表述:描述世界时什么样
  • 规范表述:描述世界应该是什么样

相互依存性和贸易的好处

  • 绝对优势:一个生产者用比另一个生产者更少的投入生产某种物品的能力
  • 比较优势:一个生产者以低于另一个生产者的机会成本生产某种物品的能力

市场如何运行

供给和需求的市场力量

  • 市场:由某种物品或服务的买者与卖者组成的群体
  • 竞争市场:买者和卖者都很多,以至于每个人对市场价格的影响都微乎其微
  • 需求量:买者愿意并且能够购买的一种物品的数量
  • 需求定理:其他条件不变时,价格和物品的需求量成反比
  • 正常物品:随着收入增加需求量增加的物品
  • 低档物品:随着收入增加需求量减少的物品
  • 替代品:一个物品价格的上升引起另一种物品需求量上升的物品
  • 互补品:一个物品价格的上升引起另一种物品需求量下降的物品
  • 供给量:卖者愿意并且能够出售该物品的数量
  • 供给定理:其他条件不变时,价格和物品的供给量成正比
  • 均衡:市场价格达到是供给量和需求量相等的状态
  • 均衡价格(市场出清价格):使供给和需求平衡的价格
  • 供求定理:认为任何一种物品的价格都会自发调整并达到平衡

弹性及其应用

  • 弹性:更亮需求量或供给量对某种决定因素的变动的反应程度指标
  • 总收益:对于一种物品,买者支付而卖者得到的量
  • 需求收入弹性:消费者收入变动程度对一种物品需求量变动程度的影响程度
  • 需求的交叉价格弹性:衡量一种物品需求量对另一种物品价格变动的反应程度
  • 供给价格弹性

供给、需求和政府政策

  • 价格上限:出售商品的法定最高价格
  • 价格下限:出售商品的法定最低价格
  • 税收归宿:税收负担在市场参与者中分配的方式

市场和福利

消费者、生产者、市场效率

  • 福利经济学:研究资源配置如何影响经济福利的学问
  • 支付意愿:买者愿意为某种物品支付的最高价
  • 消费者剩余:买者愿意为某种物品支付的量减去实际支付的量
  • 成本:卖者为了生产一种物品必须放弃的所有东西的价值
  • 生产者剩余:卖者出售一种物品得到的量减去其生产成本
  • 效率:资源配置使得社会所有成员总剩余最大化的性质
  • 平等:社会成员平均分配经济成果的性质

赋税和国际贸易

  • 无谓损失:市场扭曲(如税收)引起的总剩余下降
  • 世界价格:一种物品在世界市场上通行的价格
  • 关税:对国外生产、国内销售的物品征税

公共部门经济学

外部性

  • 外部性:一个人的行为对旁观者福利的无补偿影响
  • 外部性内在化:改变激励,使人们考虑到自己行为的外部效应
  • 矫正税:引导私人决策者考虑外部性引起的社会成本的税收
  • 科斯定理:私人各方可以无成本地协商资源配置时,他们就可以解决外部性问题
  • 交易成本:各方在达成协议与遵守协议过程中发生的成本
  • 排他性:物品使用可以阻止另一个人使用的特性
  • 消费中的竞争性:使用一种物品将减少其他人使用的特性
  • 私人物品/公共物品/公共资源/俱乐部物品

税制

  • 预算赤字:政府支出大于收入
  • 预算盈余:政府收入大于支出
  • 边际税率:增加收入引起的额外税收
  • 平均税率:支付税收占收入的比例
  • 定额税:对每个人征收的等量的税收
  • 受益原则、支付能力原则
  • 纵向平等、横向平等
  • 比例税、累进税、累退税
  • 粘蝇纸理论

企业行为和行业组织

生产成本

  • 总收益:企业出售产品得到的货币量
  • 总成本:企业用于生产的投入品的市场价值
  • 利润:总收益 - 总成本
  • 显性成本:需要企业支出货币的投入成本
  • 隐形成本:不需要企业支出货币的投入成本
  • 经济利润:总收益 - 显性成本 - 隐性成本
  • 会计利润:总收益 - 显性成本
  • 生产函数:投入量和产量的函数
  • 边际产量:增加一单位投入引起的产量增加
  • 边际产量递减:投入边际产量随投入增加而递减的特征
  • 固定成本:不随产量变动的成本
  • 可变成本:随产量变动的成本
  • 平均总成本、平均固定成本、平均可变成本、边际成本
  • 有效规模:使总成本最小的产量
  • 规模经济、规模不经济、规模收益不变

竞争市场上的企业

  • 竞争市场:有许多交易相同产品的买者和卖者,以至于买卖双方都是价格的接受者
  • 平均收益、边际收益
  • 沉没成本:已经发生而且无法收回的成本

垄断

  • 垄断企业:一种没有相近替代品的产品的唯一卖者
  • 自然垄断:一个企业能够以低于绝大多数企业成本的方式向市场供给物品或服务产生的垄断
  • 价格歧视:对不同顾客以不同价格出售同一物品

垄断竞争

  • 寡头:只有少数几个提供相似或相同产品的卖家的市场
  • 垄断竞争:存在许多出售相似但不相同的企业的市场结构

寡头

  • 勾结:市场上的企业就生产产量或收取价格达成的协议
  • 卡特尔:联合行事的企业集团
  • 纳什均衡:相互作用而经济主体再讲其他所有主体所选策略为既定时,选择他们自己最优策略的状态
  • 囚徒困境、占优策略

生产要素市场

  • 生产要素:生产物品和服务的投入
  • 劳动的边际产量:增加一单位劳动所引起的产量增加量
  • 边际产量值:一种投入的边际产量乘以产品价格
  • 资本:用于生产物品与服务的设备和建筑物
  • 补偿性工资差别:抵消不同工作非货币特性而产生的工资差别
  • 人力资本:对人的投资的积累,如教育、在职培训
  • 歧视:对仅仅是种族、民族、性别、年龄或其他个人特征不同的相似个人提供不同机会
  • 贫困率、贫困线
  • 功利主义:主张政府应该选择使社会上所有人总效用最大化
  • 自由主义、自由至上主义
  • 负所得税:向高收入人群征税给低收入家庭补助

深入探讨的论题

  • 预算约束线:对消费者可以支付得起的消费组合的限制
  • 无差异曲线:表示给消费者同等满足程度的消费组合的曲线
  • 边际替代率:消费者愿意以一种物品交换另一种物品的比率
  • 吉芬物品:价格上升引起需求增加的物品
  • 道德风险:一个没有受到完全监督的人从事不诚实行为的倾向
  • 逆向选择:从无信息一方的角度看,无法观察到的特征组合变为不合意的倾向
  • 经济政治学:用经济学的方法研究政府
  • 康多塞悖论、阿罗不可能定理、中值选民定理

全文参考自《经济学原理》曼昆版 微观经济学分册 术语:《经济学原理》 - 微观经济学原理笔记 附:术语 宏观经济学:《经济学原理》 - 宏观经济学原理笔记

导言

经济学十大原理

  • 稀缺性指社会资源有限,不能生产人们希望的所有物品和服务。
  • 经济学研究社会如何管理自己的稀缺资源

经济学有些核心思想,十大原理可以做一个简要的概括。经济由群体中的个人组成,因此个人的行为可以反映经济的行为。下面从个人角度分类举出这些原理。

人们如何做出决策

  • 原理1:人们总会面临权衡取舍
  • 原理2:某种东西的成本是为了得到它需要舍弃的东西(机会成本)
  • 原理3:理性人考虑边际量。一个人对任何物品的支付意愿基于增加1单位物品获得的边际收益。当且仅当一个行为的边际收益大于边际成本时,理性决策者才会采取这个行为
  • 原理4:人们会对激励做出反应。因为理性人会通过比较成本和收益做出决策。比如降息会激励人们取出储蓄拿来投资。我们在分析决策时,不仅要考虑直接影响,还应该能考虑通过激励造成的间接影响

人们如何相互影响

  • 原理5:贸易可以使每个人的状况都变得更好,即非零和。
  • 原理6:市场通常是组织经济活动的一种好方法。根据亚当·斯密的观察结果,市场经济中价格作为一只“看不见的手”指引经济活动。它的推论是,任何限制或阻碍这只手的行为会扭曲家庭和企业的决策,并造成不良影响。比如税收、中央计划经济。
    • 市场经济中,参与者受利己心的驱动,但往往比他处于公共利益考虑时,更能有效促进公共的利益
    • “让人们各行其是,不要让政府沉重的手知道他们的行为,结果往往会最好”
  • 原理7:政府有时可以改善市场结果
    • 政府制定制度,通过权威以便个人可以拥有并控制稀缺资源
    • “看不见的手”考虑不了外部性市场势力这两种市场失灵的情况。因为需要政府进行干预,以促进效率或促进平等

整体经济如何运行

  • 原理8:一国的生活水平取决于它生产物品和服务的能力。更细致地说,几乎所有生活水平的差别都可以归因于生产率的差别
  • 原理9:政府发行货币过多时,物价会上升,即通货膨胀。
  • 原理10:社会面临通货膨胀和失业间的短期权衡取舍
    • 货币量增加 -> 社会整体支出水平上升 -> 物品服务需求增加 -> 企业提高物价,雇佣更多的工人生产 -> 更少的失业

像经济学家一样思考

作为科学家

经济学同其他科学一样,有提出理论 -> 收集数据 -> 分析数据几个步骤,不同的是经济学同其他社会科学一样,研究的是人。

  • 同样是观察、理论、验证;经济学的验证通常只能从真实的历史事件中入手
  • 同样是简化问题,经济学中也有假设,并在假设基础上建立模型,以此了解世界
  • 第一个模型:循环流量图,描述家庭和企业的货币流转
    • 在物品与服务市场,家庭是买者,企业是卖者
    • 在生产要素市场,家庭是卖者,企业是买者
  • 绝大多数经济模型都通过数学工具构建,比如最简单的生产可能性边界
    • 表示技术和生产要素固定时,经济所能生产的产品组合
    • 曲线斜率代表某产品的机会成本
    • 曲线上的某点是当前稀缺资源的生产极限,它被称为是“有效率的”。曲线面积内的点是“无效率的”,曲线面积外的点在当前条件下无法达成。
    • 站在原点看,边界通常是向外凸出的
  • 微观经济学与宏观经济学

作为政策顾问

  • 经济学家分析世界时是科学家,帮助改善世界时,它们是政策顾问(工程师)
  • 实证表述规范表述
    • 实证表述通过证据验证;规范表述除了证据还会涉及道德、政治哲学等价值观
    • 经济学中的大多数内容都是实证表述,站在科学家立场上的
  • (个人感悟)世界由自然科学家们定义和主导,而“人”则由社会科学家(如经济学家、哲学家)们定义和主导
  • 经济学家只是施政的一个影响因素而已,最终政策是多方角力的结果

造成经济学家矛盾的原因

  • 科学判断不同,这与自然科学一致。
  • 价值观不一致

附:图表

  • 通常用图形直观地说明一组事件如何引起另一组事件的发生
  • 两个陷阱:变动由未画出的第三个变量引起;反向因果关系
    • 打火机和癌症的正相关
    • 家用旅行车和家庭人口增加的正相关

相互依存性和贸易的好处

  • 出发点是:贸易可以使每个人状况都变得更好

简单的经济学寓言

  • 自给自足时,生产可能性边界即消费可能性边界。
  • 相互贸易时,由于专业化,每人专注于擅长的工作,双方的消费可能性边界将大于生产可能性边界

比较优势:专业化的动力

  • 绝对优势和比较优势
  • 比较优势用机会成本衡量,所以两个生产者间相互比较,比较优势一定是有高有低而不会都较高的
  • 不同的机会成本导致贸易可以增加经济总产量,每个人专门生产自己有比较优势的物品。同时由于机会成本不同,双方都可以议价,并以低于自己生产某物品机会成本的价格得到该物品从而从贸易中获益
  • 比较优势原理:贸易可以使社会上每个人都获益,因为它使人们可以专门从事他们具有比较优势的活动。这也是经济学家反对贸易限制的主要依据
  • 通过上面分析还能得到一个结论:由于双方都要获益,因此贸易的价格要在两种机会成本之间才能达成交易

比较优势的应用

  • Tom Fordy应该雇人修剪草坪,而去拍广告
  • 自由贸易中,每种物品应该由生产这种物品机会成本较低的国家生产

市场如何运行

供给与需求的市场力量

市场与竞争

  • 比较优势说明贸易可以使双方状况都变好,而物品和服务是通过市场中的供给与需求交流的
  • 供给和需求是人们在市场上相互交易的行为
    • 市场上,买者决定需求,卖者决定供给
  • 完全竞争的两个特征 / 价格接受者 / 垄断

需求

  • 需求定理:需求量和价格成反比
  • 区分市场需求和个人需求
  • 影响需求曲线的一些因素
    • 收入:正常物品和低档物品
    • 相关物品的价格:替代品
    • 爱好、预期、买者总量

供给

  • 供给定理:价格和供给量成正比
  • 区分市场供给和个人供给
  • 影响供给曲线的一些因素
    • 投入品价格
    • 技术
    • 预期、卖者数量

需求和供给的结合

  • 市场的均衡是上述两条线的交点
    • 均衡价格(市场出清价格)
    • 过剩和短缺(沿着曲线移动
    • 供求定理:认为任何一种物品的价格都会自发调整并达到平衡
  • 均衡变动:曲线的移动、新平衡的达成
    • 判断影响的是供给还是需求还是都有
    • 区分供给变动供给量变动需求变动需求量变动
  • 价格决定了社会稀有资源的配置 / 一只看不见的手

弹性及其应用

  • 需求价格弹性和影响因素
    • 可替代品的可获得性/必需品和奢侈品/市场和时间的范围
  • 计算方式:需求量变动百分比 / 价格变动百分比
    • 中点法,避免同一场景的不同方向得到不同结果
  • 弹性值和需求曲线的斜率
    • 富有弹性、缺乏弹性、单位弹性
  • 收益的计算:数目 * 价格
    • 富有弹性时,价格上升引起收益增加
    • 缺乏弹性时,价格上升引起收益减少
  • 需求收入弹性和需求交叉价格弹性

一些应用的例子:

  • 小麦技术的进步减少了农民收入,鼓励人们离开农业
  • OPEC不能长期维持高油价
  • 禁毒在短期内会增加毒品相关犯罪

供给、需求和政府政策

价格控制

  • 限制性约束的价格上限(低于均衡价格)将造成物品短缺,引起稀缺物品分配效率的降低
    • 限制油价
    • 长期的租金控制引起人们租不到房,房东不愿意优化自己的房
  • 同样地,限制性约束的价格下限很容易引起过剩
    • 劳动力市场的最低工资会导致失业
    • 计划经济导致生活必需品的缺乏

税收

  • 税收抑制了市场活动,导致物品销售量减少,减少了市场规模,同时买者和卖者分摊了税收负担。
  • 对买者征税和对卖者征税是相同的,税收归宿决定于供给和需求的力量。
  • 税收楔子与相对弹性
    • 更有弹性的一方承担较少的部分,税收负担更多由缺乏弹性的市场一方承担
    • 应用:工薪税更多由劳动者承担;奢侈品税由奢侈品供应者承担

市场和福利

消费者、生产者、市场效率

  • 福利经济学,讨论资源配置和经济福利的关系
  • 消费者参与市场的收益 - 支付意愿和消费者剩余
    • 图表表示:需求曲线以下和价格以上的面积
    • 实际意义:衡量买者从一件物品中得到自我感觉的利益,通常情况下,也可以反映经济福利程度
  • 生产者参与市场的收益 - 成本和生产者剩余
    • 图表表示:价格以下和供给曲线以上的面积
    • 实际意义:衡量卖者的福利程度
  • 市场效率、平等
    • 总剩余:生产者剩余 + 消费者剩余
    • 效率和平等
    • 自由市场把物品供给分配给对这些物品评价最高的买者,评价用购买意愿衡量
    • 自由市场把物品的需求分配给能够以最低成本生产这些物品的卖者
    • 自由市场生产出使消费者和生产者剩余总和最大化的物品量
  • 之前的讨论都建立在假设的基础上、市场失灵时,市场无法有效地配置资源
    • 非完全竞争:市场势力
    • 外部性
  • 应用
    • 不论是供给提高(技术演进、成本降低)还是需求提高,都能提高生产者、消费者剩余,即市场效率。间接地,,也会促进互补品的繁荣,引起替代品的消亡

赋税的代价

  • 税收收入的矩形表示 => 社会总剩余的下降
  • 买者和卖者因税收遭受的损失大于政府筹集到的收入
  • 税收引起的无谓损失因为它使卖者和买者不能实现贸易的好处,这个好处可以用税收楔子的三角形衡量。三角形内的贸易带来的剩余由于小于税收被阻止。
  • 供给和需求的弹性越大,税收带来的无谓损失就越大
    • 无谓损失越大,政府实施一项计划的成本就越高
  • 政府的税收收入随着征税的增长会先变大再变小,而无谓损失是一直扩大的

国际贸易

  • 国内价格反映了物品的机会成本,即国内具有比较优势的商品
  • 假定世界价格是既定的,用世界价格线和供求线形成的三角形表示进出口国收益
    • 世界价格较低时,消费者剩余增加,生产者剩余减少,总体收益
    • 世界价格较高时,消费者剩余降低,生产者剩余增加,总体收益
    • 贸易可以使每个人的情况都变好
  • 关税和无谓损失
    • 关税使价格更逼近均衡价格,减少了进口量,但带来了无谓损失
    • 无谓损失来自过度生产和消费不足
  • 贸易在消灭一些工作岗位的同时,也创造了比较优势行业上的工作岗位(保护主义)
  • 自由贸易在提高效率的同时,可以会牺牲平等

公共部门经济学

外部性

  • 正外部性和负外部性
  • 外部性内在化
    • 负外部性使市场生产数量大于社会合意数量,正外部性则相反
    • 对正外部性补贴,负外部性征税
  • 如何针对
    • 命令和控制 —— 管制
    • 以市场为基础 —— 矫正税和补贴
    • 可交易的污染量 —— 污染许可证
  • 矫正税鼓励公司开发更环保的技术,比管制更灵活,同时还能增加政府收入
  • 矫正税决定了污染价格,污染许可证决定了污染量
  • 外部性的私人解决办法
    • 道德规范 & 慈善行为
    • 外部性内在化是一些企业进行多类型经营的一个原因
  • 科斯定理:私人可以有效率地解决外部性
    • 交易成本影响科斯定理

公共物品和公共资源

  • 私人市场不能保证没有价格的物品的适当配置
  • 私人物品/公共物品/公共资源/俱乐部物品
  • 公共物品
    • 公共物品的总利益大于成本时,就可以不考虑搭便车者的存在
    • 公共物品的成本-收益分析:并不像私人物品市场,买者和卖者通过出价表达物品的评价和成本
  • 公共资源
    • 公地悲剧:一个人使用公共资源会减少他人使用,由于负外部性的存在,公共资源往往被过度使用
    • 解决措施:征收矫正税或颁发许可证;将公共资源变为私人物品
    • 举例:清洁的空气、水、拥堵的道路、动植物资源等
  • 为什么象牙的商业价值是大象的噩梦,而奶牛的商业价值却是它的护身符呢?
    • 因为大象是公共资源,而奶牛是私人物品
    • 产权缺失引起市场失灵,政府可以释放市场的力量,从而让资源配置更有效率,增进经济福利

税制

联邦政府

  • 收入:个人所得税、社会保险税(工薪税)、公司所得税、销售税
  • 支出:收入保障、医疗、国防、债券利息
  • 赤字和盈余
    • 赤字可以通过发行政府债券筹资,并在盈余时偿还
    • 人口老龄化带来的财政挑战

地方政府

  • 收入:销售税、财产税、许可证收费、公共交通收费
  • 支出:教育、医疗

税收的效率

  • 税收的成本来自于扭曲决策时的无谓损失和纳税人承担的管理负担
  • 消费税的转型
  • 边际税率和平均税率
  • 定额税:有效率但无法保证平等

税收的平等

  • 受益原则:认为人们应该根据从政府服务的收益多少来纳税
  • 支付能力原则:认为应该根据人们可承受负担来纳税
    • 纵向平等:支付能力强的人多纳税
    • 比例税、累进税、累退税
    • 横向平等:相似支付能力的人纳税相似
  • 税收归宿和税收平等
    • 粘蝇纸理论

企业行为和产业组织

生产成本

  • 我们通常可以假设:企业的目标就是利润最大化
  • 收益、成本、利润的计算
  • 机会成本:显性、隐性成本
    • 容易被忽略的隐性成本
  • 经济利润与会计利润
    • 区别:是否考虑隐性成本
    • 经济利润是企业经营者供给物品或服务的动机源泉

生产与成本

  • 生产函数:投入量和产量的函数
  • 边际产量、边际产量递减
  • 总成本曲线:产量和总成本的关系函数
    • 在边际产量递减时,生产函数越来越平坦,而总成本曲线越来越陡峭
    • 由于投入量和成本的近似性,生产函数几乎是总成本曲线的反函数
  • 固定成本:租金、人力等
  • 可变成本:投入品、时薪
  • 平均总成本(ATC)、平均可变成本(AVC)、边际成本(MC)
    • 递增的边际成本
    • U形的平均总成本
    • U形平均总成本的最低点对应的产量叫做有效规模
  • 边际成本曲线和平均总成本曲线在有效规模处相交
  • 典型的成本曲线三个特征
    • 最终递增的边际成本曲线
    • U形的平均总成本曲线
    • 两者相交于有效规模处

短期和长期成本

  • 企业的长期成本曲线不同于短期成本曲线
    • 大、中、小型工程的ATC曲线
  • 规模经济、规模不经济、规模收益不变
    • 长期平均总成本随产量增加的几种变化情况
    • 规模经济通常来自专业化和分工,规模不经济通常来自沟通成本和协调问题
  • 愈精细的分工(专业化)愈容易带来规模经济

竞争市场上的企业

竞争市场

  • 竞争市场
    • 市场上有众多买家、卖家
    • 交易的物品大体相同
    • 企业可以自由进入或退出市场
  • 平均收益:物品的价格
  • 边际收益:对竞争企业来说,边际收益等于物品价格

利润最大化

  • 通过比较边际收益和边际成本,可以找到利润最大化的产量,因此对于竞争企业来说,利润最大化的产量点即价格和边际成本曲线的交点
    • 边际成本小于边际收益时,增加产量
    • 边际成本大于边际收益时,减少产量
    • 两者相等时,利润最大化
  • 实际上,企业的边际曲线决定了企业在任何价格时愿意供给的物品数量,即供给曲线

短期/长期决策

  • 短期供给曲线:价格(平均收益)小于平均可变成本(AVC)时,企业停止营业,大于AVC时,产量沿着MC曲线移动
  • 沉没成本的无关性短期内,供给曲线和固定成本没有关系
    • 应用:弄丢了电影票不影响再买一张的决定、淡季的餐馆和高尔夫球场的决策
  • 长期供给曲线:价格(平均收益)小于平均总成本(ATC)时,企业退出市场,进入的标准刚好相反
  • 利润的图形表示

竞争市场的供给曲线

上面讨论的单个企业的短期、长期供给决策,下面看下市场上短期和长期的供给曲线

  • 短期:企业数目固定,供给曲线等于边际成本曲线的叠加
  • 长期:企业可以自由离开和加入,达到均衡时,留在市场中的企业利润必定为0。此时,价格=ATC,而对企业而言,会选择让价格=MC保证利润最大化,所以最终使ATC=MC,让市场中每个企业都达到有效规模,供给曲线等于固定价格,完全富有弹性
  • 由于这里的成本是机会成本,实际上会计成本是大于0的,所以企业还会留在市场中
  • 短期、长期内的需求移动
    • 短期内带来企业的盈利、亏损
    • 长期内随着企业离开和进入市场,价格回到长期均衡
  • 长期供给曲线可能会向右上方倾斜
    • 生产资源数量有限
    • 鼓励新企业加入,就需要提高价格 -> 甚至能有企业长期盈利

垄断

  • 垄断企业是价格决定者
  • 垄断企业的进入壁垒
    • 垄断资源
    • 政府管制:版权和专利
    • 生产流程:规模经济产生的自然垄断,一个企业能够以低于其他企业的成本供应产品
  • 为保证能卖出产品,垄断企业的需求曲线斜向右下方
    • 垄断者的边际收益总小于物品价格
  • 在垄断企业利润最大化时,P > MR = MC
    • 先找到MC = MR的生产数量点,再对应需求曲线找到合适定价的价格
    • 在市场竞争者增多时,价格会逐渐回落到等于边际成本

垄断的福利代价

  • 无谓损失:垄断者生产的产量总小于社会有效率的产量
    • 类似于收税:这里私人企业得到的“税收”正是垄断利润
    • 对应到现实生活,无谓损失即无效率的低产量

价格歧视

根据消费者对商品的评价差异化确定价格。

  • 竞争市场中,不会出现物品的价格歧视
  • 价格歧视可以实现垄断者的利润最大化
  • 价格歧视要求能够根据支付意愿划分顾客
  • 价格歧视可以增进社会福利,不过是生产者的剩余
  • 价格歧视增加了垄断利润,完全价格歧视可以让生产者获取市场的全部剩余,避免无谓损失,然而实际中通常做不到
    • 举例:电影票、飞机票、折扣券、数量折扣

针对垄断的公共政策

  • 增加市场竞争性:反托拉斯法
  • 管制:直接限制垄断企业的定价
  • 公有制:政府自己经营 -> 带来市场效率下降
  • 不作为

垄断竞争

既有竞争性又有垄断性的市场,比如小说。

  • 寡头,集中率衡量
  • 垄断竞争:许多卖者产品有差别自由进出
  • 市场组织的分类
    • 垄断
    • 寡头
    • 垄断竞争
    • 完全竞争

差别产品竞争

  • 短期中,垄断竞争的分析方式和垄断一样
  • 长期中,企业可以自由进出,并最终达到利润为0的情况,即MR=MC,P=ATC。价格曲线和平均总成本曲线相切
  • 一些结论,均衡点在ATC变小的部分,此时MC < ATC
    • 在长期均衡下,对比完全竞争,产量是小于有效规模的,即有过剩生产能力
    • 高于边际成本的价格加成,因此此时,每新增一个客户,都会使生产者利润增加,生产者有激励去吸引更多顾客
  • 因为P > ATC,垄断竞争也会带来无谓损失

广告

  • 由于垄断企业出售价格大于边际成本,因此都有激励做广告来吸引买者买自己的特定产品
    • 产品间差异越大的行业,收益中用于广告的成本越大
    • 总体来说,广告促进了竞争
  • 广告本身的质量与否影响着人们对产品质量的评价

寡头

  • 勾结、卡特尔:禁止卡特尔内协商生产数目或价格是困难的
  • 纳什均衡的达成
    • 寡头价格低于垄断价格,但高于竞争价格
    • 随着企业的增多,市场会越来越接近竞争市场
  • 寡头和囚徒困境:维持合作是困难的
    • 军备竞赛
    • 公共资源
    • 寡头的囚徒困境对社会是有益的
  • 多次合作能让合作者更关注长远利益、而避免囚徒困境
  • 贸易限制、托拉斯法
  • 一些看似的反竞争操作,可能有合理的经营目的
    • 转售价格维持
    • 掠夺性定价
    • 搭售

劳动市场经济学

生产要素市场

生产要素需求是派生需求,是通过向另外的市场供给物品所产生的需求

劳动的需求和供给

  • 分析前提:企业具有竞争性、企业追求利润最大化
  • 边际产量值:一种投入的边际产量乘以产品价格
  • 边际产量、边际产量递减 => 向右下方倾斜的边际产量值曲线
  • 竞争性、追求利润最大化的企业雇佣的工人数会达到使劳动边际产量等于工资的那一点,即边际产量值曲线也是劳动需求曲线
  • 工作和闲暇的权衡

劳动的均衡

这里的均衡建立在竞争市场的基础上,即工资对买卖双方来说是既定的。买方垄断的情况较少出现。

  • 均衡时,工资等于劳动的边际产量值
  • 供给、需求的移动

其他生产要素

  • 劳动、土地和资本
  • 租赁价格购买价格
    • 对于租赁价格,劳动、土地、资本各自赚到了他们在生产过程中的边际贡献的价值
    • 对比劳动收入、资本收入是通过多种方式支付给家庭的,如股利等
  • 生产要素间相互联系

工人的工资反映了他们所所生产的物品/服务的市场价格。这也解释了为何程序员的工资比加油站服务员高,IT服务业者的收入比便利店收银员高。

收入和歧视

产生收入差距的原因

  • 补偿性工资差别
  • 人力资本:对人的投资的积累。
    • 受教育程度高的工人往往有着较高的边际生产率
    • 工作效率、工具的提升,和非熟练劳动需求的转移拉开的熟练、非熟练工资的差距
    • 高等教育也是一种投资
  • 教育作为一种信号
  • 能力、努力和机遇
  • 超级明星
    • 市场上每个人都想享受最优生产者提供的物品
    • 生产物品的技术使最优生产者低成本提供物品成为可能
  • 最低工资法、工会、效率工资

歧视经济学

  • 劳动市场上的歧视并不能直观地分析
  • 竞争市场会对雇主的歧视做“自然的矫正”,那些只对赚钱有兴趣的企业占据优势地位
    • 这种歧视只有在顾客偏好政府政策存在时,才能维持下去

收入不平等和贫困

  • 贫困率、贫困线
    • 影响衡量不平等的因素:实物转移支付、生命周期、暂时收入和持久收入
    • 实质生活水平上的不平等比年收入的不平等要小得多
  • 收入再分配的政治哲学
    • 功利主义:社会效用最大化
    • 自由主义:政策需要客观公正,即由对社会现状一无所知的社会参与者得出
      • 最大最小准则:主张应该使社会上状况最差的人福利最大化
    • 自由至上主义:预先设定规则,惩罚违规者,强调过程而非结果,不进行收入再分配
  • 减少不平等的政策
    • 最低工资
    • 福利
    • 负所得税、劳动所得税减免
    • 实物转移支付
    • 反贫困计划、工作激励

深入探讨的论题

消费者选择理论

  • 预算约束曲线:在既定收入下,消费某种物品引起另一种物品消费量的变化
  • 消费者偏好:无差异曲线、边际替代率
  • 无差异曲线的4个特征
    • 较高的无差异曲线给消费者的满足感更高
    • 无差异曲线向右下方倾斜
    • 无差异曲线不相交
    • 无差异曲线凸向原点
  • 完全替代品和完全互补品
    • 完全替代品:边际替代率为定值,一条直线
    • 完全互补品:无差异曲线为直角

消费者选择什么

  • 消费者选择什么:最优点
    • 最优点处,消费者选择的两种物品组合要使边际替代率等于相对价格
    • 相对价格和边际交换率分别代表市场和消费者对两种物品的评价
    • 效用来描述最优点的平衡状态:对X物品支出的每美元的边际效用等于用于Y物品支出的每美元的边际效用
  • 收入变动对选择的影响
    • 正常物品和低档物品
  • 价格变动对选择的影响
    • 预算约束线的外扩
    • 收入效应:向更高无差异曲线移动引起的消费变动
    • 替代效应:沿着无差异曲线变动到不同标记替代率的点的消费变动
  • 收入效应、替代效应的应用
    • 吉芬物品:价格上升引起需求增加,和物品的低档程度有关
    • 工资如何影响劳动供给:取决于劳动者如何衡量收入效应和替代效应

微观经济学前沿

不对称信息

  • 隐蔽性行为和道德风险:代理人和委托人
    • 公司管理中,股东、董事会和管理层就分属委托人和代理人,道德风险即管理层可以做出违背股东利益的公司决策
  • 隐蔽性特征:逆向选择
    • 卖者了解得更多,买者承担风险
    • 有信息一方披露信息:发信号
    • 无信息一方迫使有信息一方披露信息:筛选

政府经济学

用经济学的方法分析政府

  • 康多塞悖论:(多于两种选择时)多数原则没有产生可传递的社会偏好
    • 投票顺序会影响结果
    • 多数投票本身可能并不能告诉我们社会想要什么结果
  • 阿罗不可能定理:没有一种投票制度可以满足下列所有条件
    • 确定性
    • 传递性
    • 不相关选择的独立性:任何两个结果之间的排序不取决于别的结果
    • 没有独裁者
  • 阿罗不可能定理意味着无法把社会成员的个人偏好加总成社会偏好
  • 中值选民定理:多数原则将产生中值选民最偏好的结果
    • 前提
    • 应用:大选时,两党都会尽量争取中值选民的支持,因此政治主张也会趋同

行为经济学

社会心理学和经济学的融合

  • 人不总是理性:左位偏差
  • 人想要公平
  • 人是善变的
0%