Dart(2.2) - 類(Classes)

類(Classes)

Dart 是一種面向?qū)ο笳Z言被冒,包含類和基于mixin的繼承兩部分。每個(gè)對(duì)象是一個(gè)類的實(shí)例轮蜕,并且 Object 是所有類的父類昨悼。基于mixin的繼承指的是每個(gè)類(除了Object)都只有一個(gè)父類肠虽,類體還可以在多個(gè)類繼承中被重用幔戏。

使用類成員(Using class members)

對(duì)象的成員包含函數(shù)(functions)和數(shù)據(jù)(data)。當(dāng)你調(diào)用一個(gè)方法(method)的時(shí)候税课,方法能夠訪問對(duì)象的函數(shù)和數(shù)據(jù)

使用點(diǎn)(.)語法引用實(shí)例變量和方法

var p = Point(2, 2);

// Set the value of the instance variable y.
p.y = 3;

// Get the value of y.
assert(p.y == 3);

// Invoke distanceTo() on p.
num distance = p.distanceTo(Point(4, 4));

使用 ?.來替代.可以避免當(dāng)左邊對(duì)象為null時(shí)候拋出異常:

// If p is non-null, set its y value to 4.
p?.y = 4;

使用構(gòu)造器(Using constructors)

你可以使用構(gòu)造器創(chuàng)建對(duì)象闲延,構(gòu)造器的名字可以是類名(ClassName)痊剖,或者類名.標(biāo)識(shí)符(ClassName.identifier)形式。例如:下面的代碼使用了Point()Point.fromJson()構(gòu)造器來創(chuàng)建Point對(duì)象

var p1 = Point(2, 2);
var p2 = Point.fromJson({'x': 1, 'y': 2});

下面的代碼是相同的效果垒玲,在構(gòu)造器之前使用可選的new關(guān)鍵字

var p1 = new Point(2, 2);
var p2 = new Point.fromJson({'x': 1, 'y': 2});

new關(guān)鍵字在Dart2中成為可選

一些類提供常量構(gòu)造函數(shù)(constant constructors)陆馁,要?jiǎng)?chuàng)建一個(gè)編譯時(shí)用的常量構(gòu)造函數(shù),使用const關(guān)鍵字代替new

var p = const ImmutablePoint(2, 2);

構(gòu)造兩個(gè)等同的編譯時(shí)常量其實(shí)是同一個(gè)對(duì)象:

var a = const ImmutablePoint(1, 1);
var b = const ImmutablePoint(1, 1);

assert(identical(a, b)); // They are the same instance!

const上下文中合愈,你能夠在構(gòu)造器或者字面量之前省略const叮贩,比如:創(chuàng)建一個(gè)常量的map

// Lots of const keywords here.
const pointAndLine = const {
  'point': const [const ImmutablePoint(0, 0)],
  'line': const [const ImmutablePoint(1, 10), const ImmutablePoint(-2, 11)],
};

我們可以只留第一個(gè)const關(guān)鍵字即可

// Only one const, which establishes the constant context.
const pointAndLine = {
  'point': [ImmutablePoint(0, 0)],
  'line': [ImmutablePoint(1, 10), ImmutablePoint(-2, 11)],
};

如果常量構(gòu)造器不再常量上下文(constant context)范圍內(nèi)并且沒有使用const關(guān)鍵字,那么該對(duì)象不是常量對(duì)象

var a = const ImmutablePoint(1, 1); // Creates a constant
var b = ImmutablePoint(1, 1); // Does NOT create a constant

assert(!identical(a, b)); // NOT the same instance!

注意:在Dart2const關(guān)鍵字在常量上下文中是可選的

獲取對(duì)象的類型(Getting an object’s type)

為了在運(yùn)行時(shí)獲取對(duì)象的類型佛析,可以使用runtimeType屬性益老,它返回 Type對(duì)象

print('The type of a is ${a.runtimeType}');

實(shí)例變量(Instance variables)

下面是如何定義實(shí)例變量的示例:

class Point {
  num x; // Declare instance variable x, initially null.
  num y; // Declare y, initially null.
  num z = 0; // Declare z, initially 0.
}

所有沒有初始化的變量值都是null

每個(gè)實(shí)例變量都會(huì)自動(dòng)生成一個(gè)getter方法(隱含的)寸莫。Non-final實(shí)例變量還會(huì)自動(dòng)生成一個(gè)setter方法捺萌。詳情參考Getters and setters

class Point {
  num x;
  num y;
}

void main() {
  var point = Point();
  point.x = 4; // Use the setter method for x.
  assert(point.x == 4); // Use the getter method for x.
  assert(point.y == null); // Values default to null.
}

如果你在實(shí)例變量定義的時(shí)候初始化該變量(不是 在構(gòu)造函數(shù)或者其他方法中初始化),該值是在實(shí)例創(chuàng)建的時(shí)候初始化的膘茎,也就是在構(gòu)造函數(shù)和初始化參數(shù)列表執(zhí)行之前桃纯。

構(gòu)造函數(shù)(Constructors)

定義一個(gè)和類名字一樣的方法就定義了一個(gè)構(gòu)造函數(shù),還可以帶有其他可選的標(biāo)識(shí)符披坏,詳情參考 Named constructors(命名構(gòu)造函數(shù))态坦。常見的構(gòu)造函數(shù)生成一個(gè)對(duì)象的新實(shí)例:

class Point {
  num x, y;

  Point(num x, num y) {
    // There's a better way to do this, stay tuned.
    this.x = x;
    this.y = y;
  }
}

this 關(guān)鍵字指當(dāng)前的實(shí)例。

注意: 只有當(dāng)名字沖突的時(shí)候才使用this棒拂。否則的話伞梯, Dart代碼風(fēng)格樣式推薦忽略this

由于把構(gòu)造函數(shù)參數(shù)賦值給實(shí)例變量的場(chǎng)景太常見了帚屉, Dart提供了一個(gè)語法糖來簡(jiǎn)化這個(gè)操作:

class Point {
  num x;
  num y;

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

默認(rèn)構(gòu)造函數(shù)(Default constructors)

如果你不聲明一個(gè)構(gòu)造函數(shù)壮锻,系統(tǒng)會(huì)提供默認(rèn)構(gòu)造函數(shù)。默認(rèn)構(gòu)造函數(shù)沒有參數(shù)涮阔,它將調(diào)用父類的無參數(shù)構(gòu)造函數(shù)。

構(gòu)造函數(shù)不能繼承(Constructors aren’t inherited)

子類不繼承父類的構(gòu)造函數(shù)灰殴。子類只有默認(rèn)構(gòu)造函數(shù)(無參數(shù)敬特,沒有名字的構(gòu)造函數(shù))。

命名構(gòu)造函數(shù)(Named constructors)

使用命名構(gòu)造函數(shù)可以為一個(gè)類聲明多個(gè)構(gòu)造函數(shù)牺陶,或者說是提供額外的聲明:

class Point {
  num x, y;

  Point(this.x, this.y);

  // Named constructor
  Point.origin() {
    x = 0;
    y = 0;
  }
}

記住伟阔,構(gòu)造函數(shù)不能繼承,這意味著子類不會(huì)繼承父類的構(gòu)造函數(shù)掰伸。如果你希望子類在創(chuàng)建之后能夠擁有在父類中聲明的命名構(gòu)造函數(shù)皱炉,你就必須在子類中實(shí)現(xiàn)該構(gòu)造函數(shù)。

調(diào)用非默認(rèn)的父類的構(gòu)造函數(shù)(Invoking a non-default superclass constructor)

默認(rèn)情況下狮鸭,在子類的構(gòu)造函數(shù)將會(huì)調(diào)用父類的無參數(shù)構(gòu)造函數(shù)合搅。父類的構(gòu)造函數(shù)在子類構(gòu)造函數(shù)體開始執(zhí)行的位置調(diào)用多搀。 如果提供了一個(gè) initializer list(初始化參數(shù)列表) ,則初始化參數(shù)列表在超類構(gòu)造函數(shù)執(zhí)行之前執(zhí)行灾部。 下面是構(gòu)造函數(shù)執(zhí)行順序:

    1. initializer list(初始化參數(shù)列表)
    1. superclass’s no-arg constructor(超類的無參構(gòu)造函數(shù))
    1. main class’s no-arg constructor(主類的無參構(gòu)造函數(shù))

如果父類沒有無名無參數(shù)構(gòu)造函數(shù)康铭, 則你需要手工的調(diào)用父類的其他構(gòu)造函數(shù)。 在構(gòu)造函數(shù)參數(shù)后使用冒號(hào) (:) 可以調(diào)用父類構(gòu)造函數(shù)赌髓。

class Person {
  String firstName;

  Person.fromJson(Map data) {
    print('in Person');
  }
}

class Employee extends Person {
  // Person does not have a default constructor;
  // you must call super.fromJson(data).
  Employee.fromJson(Map data) : super.fromJson(data) {
    print('in Employee');
  }
}

main() {
  var emp = new Employee.fromJson({});

  // Prints:
  // in Person
  // in Employee
  if (emp is Person) {
    // Type check
    emp.firstName = 'Bob';
  }
  (emp as Person).firstName = 'Bob';
}

由于父類構(gòu)造函數(shù)的參數(shù)在構(gòu)造函數(shù)執(zhí)行之前執(zhí)行从藤,所以參數(shù)可以是一個(gè)表達(dá)式或者一個(gè)方法調(diào)用:

class Employee extends Person {
  Employee() : super.fromJson(getDefaultData());
  // ···
}

注意:父類構(gòu)造函數(shù)的參數(shù)不能訪問this 。例如锁蠕,參數(shù)可調(diào)用靜態(tài)方法但是不能調(diào)用實(shí)方法夷野。

初始化列表(Initializer list)

除了調(diào)用父類構(gòu)造函數(shù),你也可以在構(gòu)造函數(shù)體運(yùn)行之前初始化實(shí)例變量荣倾。使用逗號(hào)分隔初始化表達(dá)式

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

注意: 初始化表達(dá)式等號(hào)右邊的部分不能訪問 this悯搔。

重定向構(gòu)造函數(shù)(Redirecting constructors)

有時(shí)候一個(gè)構(gòu)造函數(shù)會(huì)調(diào)動(dòng)類中的其他構(gòu)造函數(shù)。 一個(gè)重定向構(gòu)造函數(shù)是沒有代碼的逃呼,在構(gòu)造函數(shù)聲明后鳖孤,使用冒號(hào)調(diào)用其他構(gòu)造函數(shù)。

class Point {
  num x, y;

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

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

常量構(gòu)造函數(shù)(Constant constructors)

如果你的類提供一個(gè)狀態(tài)不變的對(duì)象抡笼,你可以把這些對(duì)象定義為編譯時(shí)常量苏揣。要實(shí)現(xiàn)這個(gè)功能,需要定義一個(gè)const構(gòu)造函數(shù)推姻, 并且聲明所有類的變量為final

class ImmutablePoint {
  static final ImmutablePoint origin =
      const ImmutablePoint(0, 0);

  final num x, y;

  const ImmutablePoint(this.x, this.y);
}

常量構(gòu)造器并不是經(jīng)常創(chuàng)建常量平匈,更多細(xì)節(jié)看using constructors

工廠方法構(gòu)造函數(shù)(Factory constructors)

如果一個(gè)構(gòu)造函數(shù)并不總是返回一個(gè)新的對(duì)象,則使用factory來定義這個(gè)構(gòu)造函數(shù)藏古。例如增炭,一個(gè)工廠構(gòu)造函數(shù)可能從緩存中獲取一個(gè)實(shí)例并返回,或者返回一個(gè)子類型的實(shí)例拧晕。

下面代碼演示工廠構(gòu)造函數(shù)如何從緩存中返回對(duì)象隙姿。

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 = Logger._internal(name);
      _cache[name] = logger;
      return logger;
    }
  }

  Logger._internal(this.name);

  void log(String msg) {
    if (!mute) print(msg);
  }
}

注意: 工廠構(gòu)造函數(shù)無法訪問 this。

調(diào)用工廠構(gòu)造函數(shù)根其他構(gòu)造器一樣

var logger = Logger('UI');
logger.log('Button clicked');

函數(shù)(Methods)

函數(shù)是類中定義的方法厂捞,是類對(duì)象的行為输玷。

實(shí)例函數(shù)(Instance methods)

對(duì)象的實(shí)例函數(shù)可以訪問this。 例如下面示例中的distanceTo()函數(shù)就是實(shí)例函數(shù):

import 'dart:math';

class Point {
  num x, y;

  Point(this.x, this.y);

  num distanceTo(Point other) {
    var dx = x - other.x;
    var dy = y - other.y;
    return sqrt(dx * dx + dy * dy);
  }
}

Getters and setters

是一種提供對(duì)方法屬性讀和寫的特殊方法靡馁。每個(gè)實(shí)例變量都有一個(gè)隱式的getter方法欲鹏,合適的話可能還會(huì)有 setter 方法。你可以通過實(shí)現(xiàn) getterssetters 來創(chuàng)建附加屬性臭墨,也就是直接使用 getset 關(guān)鍵詞:

class Rectangle {
  num left, top, width, 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;
}

void main() {
  var rect = Rectangle(3, 4, 20, 15);
  assert(rect.left == 3);
  rect.right = 12;
  assert(rect.left == -8);
}

借助于gettersetter 赔嚎,你可以直接使用實(shí)例變量,并且在不改變客戶代碼的情況下把他們包裝成方法。

注:不論是否顯式地定義了一個(gè) getter尤误,類似增量(++)的操作符侠畔,都能以預(yù)期的方式工作。為了避免產(chǎn)生任何向著不期望的方向的影響袄膏,操作符一旦調(diào)用 getter 践图,就會(huì)把他的值存在臨時(shí)變量里。

抽象方法(Abstract methods)

Instance 沉馆, gettersetter 方法可以是抽象的码党,也就是定義一個(gè)接口,但是把實(shí)現(xiàn)交給其他的類斥黑。抽象方法只能存在于抽象類(abstract classes)

要?jiǎng)?chuàng)建一個(gè)抽象方法揖盘,使用分號(hào)(;)代替方法體:

abstract class Doer {
  // Define instance variables and methods...

  void doSomething(); // Define an abstract method.
}

class EffectiveDoer extends Doer {
  void doSomething() {
    // Provide an implementation, so the method is not abstract here...
  }
}

抽象類(Abstract classes)

使用abstract定義抽象類锌奴,類不能被初始化兽狭,抽象類用于定義接口,有時(shí)會(huì)有一些實(shí)現(xiàn)鹿蜀。如果想要抽象類能夠被初始化箕慧,定義工廠構(gòu)造器

抽象類經(jīng)常擁有抽象方法,下面定義了抽象類和抽象方法

// This class is declared abstract and thus
// can't be instantiated.
abstract class AbstractContainer {
  // Define constructors, fields, methods...

  void updateChildren(); // Abstract method.
}

下面的類不是抽象的茴恰,但是定義了一個(gè)抽象函數(shù)颠焦,這樣 的類是可以被實(shí)例化的:

class SpecializedContainer extends AbstractContainer {
  // ...Define more constructors, fields, methods...

  void updateChildren() {
    // ...Implement updateChildren()...
  }

  // Abstract method causes a warning but
  // doesn't prevent instantiation.
  void doSomething();
}

隱式接口(Implicit interfaces)

每個(gè)類隱式的定義了一個(gè)接口,含有類的所有實(shí)例和它實(shí)現(xiàn)的所有接口往枣。如果你想創(chuàng)建一個(gè)支持類BAPI 的類A伐庭,但又不想繼承類B ,那么分冈,類A應(yīng)該實(shí)現(xiàn)類B的接口圾另。

一個(gè)類實(shí)現(xiàn)一個(gè)或更多接口通過用implements子句聲明,然后提供API接口要求雕沉。例如:

// A person. The implicit interface contains greet().
class Person {
  // In the interface, but visible only in this library.
  final _name;

  // Not in the interface, since this is a constructor.
  Person(this._name);

  // In the interface.
  String greet(String who) => 'Hello, $who. I am $_name.';
}

// An implementation of the Person interface.
class Impostor implements Person {
  get _name => '';

  String greet(String who) => 'Hi $who. Do you know who I am?';
}

String greetBob(Person person) => person.greet('Bob');

void main() {
  print(greetBob(Person('Kathy')));
  print(greetBob(Impostor()));
}

這里是具體說明一個(gè)類實(shí)現(xiàn)多個(gè)接口的例子:

class Point implements Comparable, Location {...}

擴(kuò)展一個(gè)類(Extending a class)

使用extends創(chuàng)建一個(gè)子類集乔,同時(shí)supper將指向父類:

class Television {
  void turnOn() {
    _illuminateDisplay();
    _activateIrSensor();
  }
  // ···
}

class SmartTelevision extends Television {
  void turnOn() {
    super.turnOn();
    _bootNetworkInterface();
    _initializeMemory();
    _upgradeApps();
  }
  // ···
}

重寫方法(Overriding members)

子類可以覆寫實(shí)例函數(shù),gettersetter坡椒。使用@override標(biāo)記方法是被重寫的

class SmartTelevision extends Television {
  @override
  void turnOn() {...}
  // ···
}

重寫操作符(Overridable operators)

下表中的操作符可以被覆寫饺著。 例如,如果你定義了一個(gè)Vector類肠牲, 你可以定義一個(gè)+函數(shù)來實(shí)現(xiàn)兩個(gè)向量相加

屏幕快照 2019-04-30 上午10.42.20.png

下面是重寫了 + 和 - 操作符的示例:

class Vector {
  final int x, y;

  Vector(this.x, this.y);

  Vector operator +(Vector v) => Vector(x + v.x, y + v.y);
  Vector operator -(Vector v) => Vector(x - v.x, y - v.y);

  // Operator == and hashCode not shown. For details, see note below.
  // ···
}

void main() {
  final v = Vector(2, 3);
  final w = Vector(2, 2);

  assert(v + w == Vector(4, 5));
  assert(v - w == Vector(0, 1));
}

如果你重寫了 == ,則還應(yīng)該重寫對(duì)象的 hashCode的getter函數(shù)靴跛。 關(guān)于重寫 ==hashCode 的示例請(qǐng)參考Implementing map keys

關(guān)于覆寫的更多信息請(qǐng)參考 Extending a class.

noSuchMethod()方法

下面是重寫Object類的 noSuchMethod()函數(shù)的例子缀雳, 如果調(diào)用了對(duì)象上不存在的函數(shù),則就會(huì)觸發(fā)noSuchMethod()函 數(shù)梢睛。

class A {
  // Unless you override noSuchMethod, using a
  // non-existent member results in a NoSuchMethodError.
  @override
  void noSuchMethod(Invocation invocation) {
    print('You tried to use a non-existent member: ' +
        '${invocation.memberName}');
  }
}

不能調(diào)用未實(shí)現(xiàn)的方法除非是下列情況之一:

  • 接收者有靜態(tài)類型dynamic
  • 接收者在未實(shí)現(xiàn)的方法中有靜態(tài)類型肥印,而且接收者的dynamic類型已經(jīng)實(shí)現(xiàn)了noSuchMethod()方法

更多信息可以看noSuchMethod forwarding specification.

枚舉類型(Enumerated types)

枚舉類型通常稱之為 enumerations 或者 enums识椰, 是一種特殊的類,用來表現(xiàn)一個(gè)固定數(shù)目的常量深碱。

使用枚舉(Using enums)

使用 enum 關(guān)鍵字來定義枚舉類型:

enum Color { red, green, blue }

枚舉類型中的每個(gè)值都有一個(gè)indexgetter 函數(shù)腹鹉, 該函數(shù)返回該值在枚舉類型定義中的位置(從 0 開始)。 例如敷硅,第一個(gè)枚舉值的位置為 0功咒, 第二個(gè)為 1.

assert(Color.red.index == 0);
assert(Color.green.index == 1);
assert(Color.blue.index == 2);

枚舉的values常量可以返回所有的枚舉值

List<Color> colors = Color.values;
assert(colors[2] == Color.blue);

可以在switch statements 中使用枚舉。如果你沒有處理所有該枚舉類型的值的話绞蹦,則會(huì)拋出一個(gè)警告:

var aColor = Color.blue;

switch (aColor) {
  case Color.red:
    print('Red as roses!');
    break;
  case Color.green:
    print('Green as grass!');
    break;
  default: // Without this, you see a WARNING.
    print(aColor); // 'Color.blue'
}

枚舉類型具有如下的限制:

  • 無法繼承枚舉類型力奋、無法使用mix in、無法實(shí)現(xiàn)一個(gè)枚舉類型
  • 無法顯示的初始化一個(gè)枚舉類型

詳情請(qǐng)參考Dart language specification

為類添加新特征:mixins(Adding features to a class: mixins)

Mixins是一種在多類繼承中重用一個(gè)類代碼的方法幽七。要使用 mixins景殷,在with關(guān)鍵字后面跟一個(gè)或多個(gè)mixin的名字 下面是示例顯示了如何使用 mixin:

class Musician extends Performer with Musical {
  // ···
}

class Maestro extends Person
    with Musical, Aggressive, Demented {
  Maestro(String maestroName) {
    name = maestroName;
    canConduct = true;
  }
}

要實(shí)現(xiàn)mixin ,就創(chuàng)建一個(gè)繼承Object類的子類澡屡,不聲明任何構(gòu)造函數(shù)猿挚,不調(diào)用 super 。除非你想mixin 不能被重用而是一個(gè)正常類驶鹉,使用mixin 關(guān)鍵字而不是class绩蜻。例如:

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 MusicalPerformer on Musician {
  // ···
}

類變量和函數(shù)(Class variables and methods)

使用 static 關(guān)鍵字來實(shí)現(xiàn)類級(jí)別的變量和函數(shù)梁厉。

靜態(tài)變量(Static variables)

靜態(tài)變量(類變量)對(duì)于類狀態(tài)和常數(shù)是有用的:

class Queue {
  static const initialCapacity = 16;
  // ···
}

void main() {
  assert(Queue.initialCapacity == 16);
}

只有當(dāng)靜態(tài)變量被使用時(shí)才被初始化辜羊。

注:本章內(nèi)容依據(jù)代碼風(fēng)格指南推薦的lowerCamelCase 來為常量命名。

靜態(tài)方法(Static methods)

靜態(tài)方法(類方法)不在一個(gè)實(shí)例上進(jìn)行操作词顾,因而不必訪問 this 八秃。例如:

import 'dart:math';

class Point {
  num x, y;
  Point(this.x, this.y);

  static num distanceBetween(Point a, Point b) {
    var dx = a.x - b.x;
    var dy = a.y - b.y;
    return sqrt(dx * dx + dy * dy);
  }
}

void main() {
  var a = Point(2, 2);
  var b = Point(4, 4);
  var distance = Point.distanceBetween(a, b);
  assert(2.8 < distance && distance < 2.9);
  print(distance);
}

注:考慮到使用高階層的方法而不是靜態(tài)方法,是為了常用或者廣泛使用的工具和功能肉盹。

你可以將靜態(tài)方法作為編譯時(shí)常量昔驱。例如,你可以把靜態(tài)方法作為一個(gè)參數(shù)傳遞給靜態(tài)構(gòu)造函數(shù)上忍。

參考

Dart

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末骤肛,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子窍蓝,更是在濱河造成了極大的恐慌腋颠,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件吓笙,死亡現(xiàn)場(chǎng)離奇詭異淑玫,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門絮蒿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來尊搬,“玉大人,你說我怎么就攤上這事土涝》鹗伲” “怎么了?”我有些...
    開封第一講書人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵但壮,是天一觀的道長(zhǎng)冀泻。 經(jīng)常有香客問我,道長(zhǎng)茵肃,這世上最難降的妖魔是什么腔长? 我笑而不...
    開封第一講書人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮验残,結(jié)果婚禮上捞附,老公的妹妹穿的比我還像新娘。我一直安慰自己您没,他們只是感情好鸟召,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著氨鹏,像睡著了一般欧募。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上仆抵,一...
    開封第一講書人閱讀 51,631評(píng)論 1 305
  • 那天跟继,我揣著相機(jī)與錄音,去河邊找鬼镣丑。 笑死舔糖,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的莺匠。 我是一名探鬼主播金吗,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼趣竣!你這毒婦竟也來了摇庙?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤遥缕,失蹤者是張志新(化名)和其女友劉穎卫袒,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體单匣,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡夕凝,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年烤蜕,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片迹冤。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖虎忌,靈堂內(nèi)的尸體忽然破棺而出泡徙,到底是詐尸還是另有隱情,我是刑警寧澤膜蠢,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布堪藐,位于F島的核電站,受9級(jí)特大地震影響挑围,放射性物質(zhì)發(fā)生泄漏礁竞。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一杉辙、第九天 我趴在偏房一處隱蔽的房頂上張望模捂。 院中可真熱鬧,春花似錦蜘矢、人聲如沸狂男。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽岖食。三九已至,卻和暖如春舞吭,著一層夾襖步出監(jiān)牢的瞬間泡垃,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來泰國打工羡鸥, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蔑穴,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓兄春,卻偏偏與公主長(zhǎng)得像澎剥,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子赶舆,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355