Dart 語言入門 (四) - Classes

Dart 語言系列

Dart 語言入門 (一)

Dart 語言入門 (二)

Dart 語言入門 (三)

Dart 語言入門 (四)

Dart 語言入門 (五)

前言

這一章不按照官方文檔的順序來沫屡,先介紹一下 Classes.

Classes

Dart 是一個面向?qū)ο蟮恼Z言抒巢,具有類和 mixin-based 繼承。 每一個對象都是一個類的實例茬贵,所有的類都是繼承自 Object. Mixin-based 繼承意味著雖然每一個類有一個超類(除了對象)蟹漓,但是類體可以在多個類的層次結(jié)構(gòu)中重用运准。

Using class members

對象包含函數(shù)和數(shù)據(jù)成員變量(分別包含方法和實例變量).
當(dāng)你調(diào)用一個方法铭乾,你可以調(diào)用一個對象:這個方法可以訪問對象的方法和數(shù)據(jù)吉拳。
使用 點. 可以引用實例變量的或者方法:

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)左邊操作數(shù)是 null:

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

Using constructors

你可以使用構(gòu)造函數(shù)創(chuàng)建一個對象豺撑。構(gòu)造名字要么是 ClassName 或者 ClassName.identifier.例如:下面的代碼創(chuàng)建 Point 對象 使用 Point()Point.fromJson() 構(gòu)造函數(shù):

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

下面的代碼有同樣的功能烈疚,但是使用可選的 new關(guān)鍵字在構(gòu)造名字之前:

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

Version note: new 關(guān)鍵字在 Dart 2 中變成可選的.

一些類提供了 constant constructors. 使用常量構(gòu)造來創(chuàng)建一個編譯期常量,在構(gòu)造函數(shù)名字前面設(shè)置關(guān)鍵字 const:

var p = const ImmutablePoint(2, 2);

創(chuàng)建兩個相同的編譯期常量會產(chǎn)生一個單獨聪轿,標(biāo)準(zhǔn)的常量:

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

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

(注:這個跟一般編程語言中的單例的實現(xiàn)類似爷肝,不過需要注意的一點是:獲取該對象的時候前面需要加上const 。)

在一個常量的上下文陆错,你可以省略const 在一個構(gòu)造函數(shù)或者文字之前灯抛。例如:看這個代碼,創(chuàng)建了一個const 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)],
};

你可以省略除了第一個使用的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)造函數(shù)在常量上下文之外并且在沒有const它的情況下調(diào)用, 它會創(chuàng)建一個 非常量對象(non-constant object):

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!

Version note: const 關(guān)鍵愛你變成可選的在常量上下文中 在Dart 2.

Getting an object’s type (獲取一個對象的類型)

在運行時為了獲取到一個類型音瓷,你可以使用對象的 runtimeType屬性对嚼,將會返回 Type 對象.

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

到這里你已經(jīng)明白如何使用 classes. 剩余的部分展示如何實現(xiàn)classes.

Instance variables

這里是如何聲明一個實例變量:

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

所有未初始化的實例變量擁有值 null.

所有的實例變量會生成一個隱式的 getter方法。Non-final 實例變量也會生成一個隱式的 setter 方法绳慎。更多細(xì)節(jié)纵竖,查看 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.
}

如果初始化聲明它的實例變量(而不是構(gòu)造函數(shù)或方法)杏愤,則在創(chuàng)建實例時該變量會被賦值靡砌,是在該實例在構(gòu)造函數(shù)及其初始化列表執(zhí)行之前忿磅。

Constructors

聲明一個構(gòu)造器通過創(chuàng)建一個和類名相同的函數(shù)(另外柬采,還有一個額外的標(biāo)識符被描述在 Named constructors. 最通常的構(gòu)造函數(shù)婉支,是生成構(gòu)造函數(shù)曾雕,創(chuàng)建一個類的新的實例:

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)前實例。

**Note:使用 this 僅僅在在有命名沖突的時汇恤。相反索守,Dart 省略了 this **

賦值構(gòu)造器參數(shù)給實例變量的形式是相同的胜茧,Dart 有語法糖使初始化更加簡單:

class Point {
  num x, y;

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

Default constructors

如果你沒有生成一個構(gòu)造函數(shù)媳瞪,將會提供一個默認(rèn)的構(gòu)造函數(shù)。默認(rèn)的構(gòu)造函數(shù)沒有參數(shù)并且在超類中會觸發(fā)無參的構(gòu)造函數(shù)照宝。

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

子類是不能夠繼承構(gòu)造函數(shù)從它的超類中蛇受。沒有聲明構(gòu)造函數(shù)的子類擁有默認(rèn)(無參,沒有名字)構(gòu)造器厕鹃。

Named constructors

使用命名的構(gòu)造函數(shù)實現(xiàn)一個類的多個構(gòu)造函數(shù)兢仰,或者提供額外的聲明:

class Point {
  num x, y;

  Point(this.x, this.y);

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

記住構(gòu)造函數(shù)不能繼承乍丈,意味著超類的命名構(gòu)造函數(shù)不能夠被子類繼承。如果你想要子類被創(chuàng)建的時候擁有一個定義在超類的命名構(gòu)造函數(shù)把将,你必須一個在子類的構(gòu)造函數(shù)轻专。

Invoking a non-default superclass constructor

默認(rèn)的,子類的構(gòu)造函數(shù)會調(diào)用超類中無名的察蹲,沒有參數(shù)的構(gòu)造函數(shù)请垛。
超類的構(gòu)造函數(shù)會被在構(gòu)造體開始之前被調(diào)用。如果使用了初始化列表(initializer list洽议,在超類被調(diào)用之前會被執(zhí)行宗收。通常,執(zhí)行順序如下;

  • 1.initializer list
  • 2.superclass’s no-arg constructor
  • 3.main class’s no-arg constructor

如果超類沒有無名亚兄,無參的構(gòu)造函數(shù)混稽,你必須手動的去調(diào)用超類中一個構(gòu)造函數(shù)。在冒號(:)之后审胚,在構(gòu)造函數(shù)體(如果有)之前指定超類構(gòu)造函數(shù)匈勋。

在下面的例子,Employee類調(diào)用其超類Person的命名構(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
}

因為在調(diào)用構(gòu)造函數(shù)之前會計算超類構(gòu)造函數(shù)的參數(shù)膳叨,所以參數(shù)可以是一個表達(dá)式洽洁,例如函數(shù)調(diào)用:

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

** Warning:超類的構(gòu)造函數(shù)的參數(shù)是不能夠訪問 this.例如: 參數(shù)可以被靜態(tài)方法調(diào)用但是不能是實例方法.**

Initializer list

除了調(diào)用父類的構(gòu)造函數(shù),你也可以初始化實例變量在構(gòu)造函數(shù)體開始之前懒鉴。使用冒號分割初始化诡挂。

// 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)');
}

Warning:初始化函數(shù)的右側(cè)是不能夠訪問 this .

在開發(fā)中,你可以使用 assert 來驗證輸入的正確性 在初始化列表中.

Point.withAssert(this.x, this.y) : assert(x >= 0) {
  print('In Point.withAssert(): ($x, $y)');
}

當(dāng)設(shè)置 final作用域時临谱,初始化列表是很方便的璃俗。下面的例子在初始化列表中初始了三個final 作用域。

import 'dart:math';

class Point {
  final num x;
  final num y;
  final num distanceFromOrigin;

  Point(x, y)
      : x = x,
        y = y,
        distanceFromOrigin = sqrt(x * x + y * y);
}

main() {
  var p = new Point(3, 4);
  print(p.distanceFromOrigin);
}
//prints 5

Redirecting constructors

有時候構(gòu)造函數(shù)的目的僅僅是在同一個類中重定向到另一個構(gòu)造函數(shù)中悉默。一個重定向的構(gòu)造函數(shù)體是空的城豁,構(gòu)造函數(shù)調(diào)用出現(xiàn)在冒號之后。

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);
}

Constant constructors

如果你有的類所創(chuàng)建的對象永遠(yuǎn)不會改變抄课,你可以使這些對象成為編譯期常量.為了做到這個唱星,定義一個 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)造函數(shù)不是總是創(chuàng)建常量.

Factory constructors

使用 factory 關(guān)鍵字 當(dāng)實現(xiàn)一個構(gòu)造函數(shù),這個構(gòu)造函數(shù)不是總創(chuàng)建新的實例跟磨。例如间聊,工廠構(gòu)造函數(shù)構(gòu)造函數(shù)可能返回一個從緩存中的實例,或者返回實例的子類型抵拘。

下面的例子證明了一個工廠構(gòu)造函數(shù)從緩存中返回一個對象:

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);
  }
}

NOTE:工廠構(gòu)造函數(shù)不能訪問 this.

調(diào)用一個工廠構(gòu)造函數(shù)和你調(diào)用其他構(gòu)造函數(shù)一樣:

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

Methods

Methods 是為對象提供行為的函數(shù)哎榴。

Instance methods

對象的實例方法可以訪問實例變量和this. distanceTo ()方法在下面的樣例中是實例方法的例子:

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

Getterssetters 為對象提供了讀和寫屬性.每一個實例都包含一個隱式的gettersetter. 如果通過實現(xiàn) getterssetter 來創(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);
}

使用 getterssetters,你可以從實例變量開始,然后使用方法包裹它們尚蝌,這一切是不需要改變客戶端代碼的迎变。

Note:無論getter是否明確定義,例如自增操作符(++)會如期運行飘言。為了避免不可以預(yù)料的副作用衣形,操作符只需調(diào)用一次getter,將其值保存在臨時變量中

Abstract methods

實例姿鸿,gettersetter 方法可以抽象谆吴,定義一個接口而把實現(xiàn)留給其他類。抽象方法僅僅存在 abstract classes般妙。

為了使方法抽象纪铺,使用分號(;) 來代替方法體:

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修飾符來定義一個抽象類- 這個類是不可以被初始化的。抽象類對于定義接口是有用的碟渺,通常還有一些實現(xiàn)鲜锚。如果你想你的抽象類可以被實例化,定義一個 factory constructor.
抽象類通常擁有 abstract methods苫拍。這里是抽象類包含抽象方法的例子:

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

  void updateChildren(); // Abstract method.
}

Implicit interfaces

每個類都隱式定義一個接口芜繁,該接口包含該類的所有實例成員及其實現(xiàn)的任何接口.你如果想要創(chuàng)建的類A支持類B的API但是并沒有繼承B類的實現(xiàn),類A應(yīng)該實現(xiàn)類B的接口绒极。
一個類實現(xiàn)一個或者多個接口統(tǒng)統(tǒng)聲明它們在 implements 條款中骏令,并且提供接口所需要的APIs.例如:

// 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()));
}

這里有指明一個類實現(xiàn)多個接口的例子:

class Point implements Comparable, Location {...}

Extending a class

使用 extends 來創(chuàng)建一個子類,并且super 來引用 超類:

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

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

Overriding members

子類可以覆蓋實例方法垄提,getter,setter. 你可以使用@override 標(biāo)注只能你想要覆蓋的成員:

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

為了抽象一個方法參數(shù)的類型或者實例變量在代碼中是 type safe ,你可以使用
covariant keyword.

Overridable operators

你可以覆蓋下面表中的運算符. 例如 : 定義 Vector 類榔袋,你可能定義一個 + 方法來相加兩個vectors.

Note:你可能要注意 != 是不能覆蓋的操作符. 表達(dá)式e1 != e2 僅僅是 !(e1 == e2) 的語法糖.

這里有一個覆蓋 +- 操作符的例子:

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)該覆蓋對象hashCode getter 方法. 覆蓋 ==hasCode,可以參考 Implementing map keys

noSuchMethod()

為了檢測或者響應(yīng)代碼是否企圖使用不存在的方法或者實體變量铡俐,你可以重寫 noSuchMethod()

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)用一個未實現(xiàn)的方法除非下列中的一個條件成立:

  • 接收者擁有一個靜態(tài)類型 dynamic
  • 接收者擁有一個靜態(tài)類型凰兑,這個類型定義了未實現(xiàn)的方法(abstract 是可以的),并且接收者的動態(tài)類型實現(xiàn)了noSuchMethod
    ,這不同于類中的對象.
    更多信息审丘,可以參照非正式的 noSuchMethod forwarding specification.

Enumerated types

枚舉類型吏够,常常被稱作 enumerations 或者 enums,是一種特殊類型的類,用來表示固定數(shù)量的常量值.

Using enums

聲明一個枚舉類型使用 enum 關(guān)鍵字:

enum Color { red, green, blue }

每一個值在枚舉中擁有一個 index getter, 將會返回一個基于零位置的值在枚舉聲明中. 例如: 第一個值索引是 0,第二值的索引是 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 語句中使用枚舉, 如果你沒有處理枚舉的值將會得到警告:

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'
}

枚舉類型有以下的限制:

  • 您不能子類化锅知,混合或?qū)崿F(xiàn)枚舉。
  • 您無法顯式實例化枚舉脓钾。

更多信息售睹,參考 Dart Language Specification.

Adding features to a class: mixins

Mixins 可以多個類的層級中重復(fù)的使用類的代碼.

要使用 mixin,使用 wtih 關(guān)鍵字后面跟上一個或者多個mixin 名字.
下面的例子展示了兩個類使用 minxins

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

要實現(xiàn) mixin, 創(chuàng)建一個類繼承 Object 并且聲明沒有構(gòu)造函數(shù)可训。除非你想要你的 mixin當(dāng)做一個標(biāo)準(zhǔn)類可以使用昌妹,要不使用 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');
    }
  }
}

為了明確只有確定類相關(guān)可以使用 minxin - 例如,你的minxin 可以調(diào)用未定義的方法 - 使用 on 來確定所必須的超類:

mixin MusicalPerformer on Musician {
  // ···
}

Version note: minxin 關(guān)鍵字是在Dart 2.1 代碼中被引入的捺宗,在早期通常使用 abstract class 代替。

注:關(guān)于minxin 更詳細(xì)的介紹和使用川蒙,可以參照這篇文章

Class variables and methods

使用 static 關(guān)鍵字來實現(xiàn)類范圍的變量和方法.

Static variables

靜態(tài)變量(類變量) 對于類范圍的狀態(tài)和常量是有用的:

class Queue {
  static const initialCapacity = 16;
  // ···
}
void main() {
  assert(Queue.initialCapacity == 16);
}

靜態(tài)變量直到他們被使用的時候才會初始化.

Static methods

靜態(tài)方法(類方法)不能操作一個實例變量蚜厉,并且不能夠訪問 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)方法當(dāng)做編譯期常量.例如畜眨,你可以傳遞一個靜態(tài)方法當(dāng)做一個參數(shù)給一個常量構(gòu)造函數(shù)昼牛。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市康聂,隨后出現(xiàn)的幾起案子贰健,更是在濱河造成了極大的恐慌,老刑警劉巖恬汁,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件伶椿,死亡現(xiàn)場離奇詭異,居然都是意外死亡氓侧,警方通過查閱死者的電腦和手機脊另,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來约巷,“玉大人偎痛,你說我怎么就攤上這事《览桑” “怎么了踩麦?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長氓癌。 經(jīng)常有香客問我谓谦,道長,這世上最難降的妖魔是什么顽铸? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任茁计,我火速辦了婚禮,結(jié)果婚禮上谓松,老公的妹妹穿的比我還像新娘星压。我一直安慰自己,他們只是感情好鬼譬,可當(dāng)我...
    茶點故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布娜膘。 她就那樣靜靜地躺著,像睡著了一般优质。 火紅的嫁衣襯著肌膚如雪竣贪。 梳的紋絲不亂的頭發(fā)上军洼,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天,我揣著相機與錄音演怎,去河邊找鬼匕争。 笑死,一個胖子當(dāng)著我的面吹牛爷耀,可吹牛的內(nèi)容都是我干的甘桑。 我是一名探鬼主播,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼歹叮,長吁一口氣:“原來是場噩夢啊……” “哼跑杭!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起咆耿,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤德谅,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后萨螺,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體窄做,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年屑迂,在試婚紗的時候發(fā)現(xiàn)自己被綠了浸策。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,696評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡惹盼,死狀恐怖庸汗,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情手报,我是刑警寧澤蚯舱,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站掩蛤,受9級特大地震影響枉昏,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜揍鸟,卻給世界環(huán)境...
    茶點故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一兄裂、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧阳藻,春花似錦晰奖、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至蛔外,卻和暖如春蛆楞,著一層夾襖步出監(jiān)牢的瞬間溯乒,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工豹爹, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留裆悄,地道東北人。 一個月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓臂聋,卻偏偏與公主長得像灯帮,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子逻住,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,592評論 2 353

推薦閱讀更多精彩內(nèi)容

  • 這是16年5月份編輯的一份比較雜亂適合自己觀看的學(xué)習(xí)記錄文檔,今天18年5月份再次想寫文章迎献,發(fā)現(xiàn)簡書還為我保存起的...
    Jenaral閱讀 2,752評論 2 9
  • 此文章是v1.0+時編寫瞎访,年代久遠(yuǎn),小心有毒吁恍,謹(jǐn)慎食用0墙铡!冀瓦! 一些重要概念 所有的東西都是對象伴奥,所有的對象都是類的...
    soojade閱讀 10,050評論 2 27
  • Dart 語言簡易教程(一): http://www.reibang.com/p/8a62b1a2fd75Dart...
    you的日常閱讀 15,118評論 4 10
  • 文丨原創(chuàng) 圖丨網(wǎng)絡(luò) 01 點一盞香燈拾徙,升一縷輕煙,譜一曲山間明月感局。孤獨尼啡,安好! 在我的眼里询微,孤獨就是一派花好月圓崖瞭。...
    紅棗饅頭閱讀 541評論 0 9
  • ??近期,公司招了一個前端撑毛,看他的代碼時书聚,有特別多的rem作為單位。對于我這種H5小菜鳥來說藻雌,沒有辦法雌续,又被強制學(xué)...
    飲水思源為名閱讀 1,041評論 0 3