青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

CG@CPPBLOG

/*=========================================*/
隨筆 - 76, 文章 - 39, 評論 - 137, 引用 - 0
數據加載中……

(ZT) 喪鐘為誰鳴?

開篇之前先說明一下,我和老莊有著不錯的私交,他最初寫喪鐘系列的時候,我是忠實的擁躉之一,莊兄見我尚有寸尺所長,還在喪鐘系列里引用了我的幾個觀點。然而最近一段時間里,我作了這樣幾件事情:

1.重新學習了lambda演算。我的數學基礎不及taowen等,費了一些時日仍不完全了然,目前大抵能對著R5RS后面的語義定義對一些簡單的scheme程序進行l(wèi)ambda演算。
2.反復研究了幾遍SICP。同時看了錄像和書(感謝曹老師下的Video),自信對前二章半有些許認識書中未及,后二章半粗知大覽尚不能發(fā)前人所未發(fā)之言。
3.學習了Smalltalk和Ruby,Duck Typing以及其他一些有關類型系統(tǒng)的東西。
4.回顧了一下面向對象語言的一些發(fā)展史,以史為鑒粗知一些興替。
5.經日和taowen,老莊討論語言、設計等等之類,每為一辨必窮我所知爭發(fā)一言,所以知識可以迅速雜糅:D

經過種種之后,發(fā)現當初所謂鳴OO之喪鐘,實在是言過其實。
--------------------------------------------------------------------------------------------------------------------------------------------------------------
第0 關于"面向對象"

既然要為人家敲喪鐘,先要找對了苦主,不然豈不是白忙活了一場。什么是面向對象?這個問題太大,我們舉一個很常見的例子:

interface Instrument {
   void playNote(Note note);
   void playChord(Chord chord);
}

abstrat class Keyboard implement Instrument {
  ..
}

class ClassicGuitar implements Instrument {
   .
}

class Piano extends Keyboard {
  ..
}

in person class

void playSolo(Instrument instrument) {
   instrument.playNote(AbsoluteNote.C1).playNote(AbsoluteNote.C2);
   
}

void playBackground(Instrument instrument) {
   instrument.playChord(Chord.C5).playChord(Chord.C9);
   
}


in some case

ClassicGuitar perez711= .
Piano pianoHere = .

vincent.playSolo(stenzel);
may.playBackground(pianoHere);

etc.

這個例子自然很不充分,不過繼承啊,接口啊,多態(tài)啊,略舉大概,尚可以作為一個討論的例子。從這個例子里,我們發(fā)現有這樣一個事實,就是Person類有兩個方法

void playSolo(Instrument instrument);
void playBackground(Instrument instrument);

分別表示,需要一個類型為Instrument的對象instrument,然后對他進行相應的操作,而且,從概念上來講,第一個方法,使演奏旋律的,也就是單音,而第二個方法是演奏和聲的。那么,如果我有一個類

class GlassBottle {

   void playNote(Note note) {
      ..
   }
}

我們知道,玻璃瓶裝了水也是可以發(fā)出聲音,Mozart可是為玻璃瓶寫過曲子的,而這里我們卻不能

GlassBottle beerBottle = .
vincent.playSolo(beerBottle);

因為我們在構造Person類的時候,我們的play方法是依賴一個類型為Instrument的Object,換而言之,我們這里所謂的 Object-Oriented其實稱作Object-with-Type-Oriented的更合適,其實這類語言有一個專有名詞,叫做static type object oriented。那Object-Oriented是不是就一定是Static Type Object Oriented的呢?不然,比如在Ruby里,我們可以寫成:

class Person 
  def playSolo(thing)
     thing.playNote(Note.C1).playNot(Note.c2)
  end
  def playBackground(thing)
     thing.playChord(Chord.C5).playChord(Chord.C9)
  end
end

class Guitar
  def playNote(note)
    
  end
  def playChord(chord)
    
  end
end

class GlassBottle
  def playNote(note)
    
  end
end

然后就可以

perez711 = Guitar.new
vincent = Person.new
vincent.playSolo(perez711)

同樣也可以

vincent.playSolo(GlassBottle.new)

在這里,類型可以推演也可以留到runtime檢查,如果是推演的話,在playNote里,由于thing調用了playNote方法,所以傳進 來的對象必須要刻意接受playNote這個消息,于是Guitar和GlassBottle都是可以通過,因此我即可以演奏我的Perez 711,也可以敲玻璃瓶。這種方式叫做dynamic type。

那么static type和dynamic type區(qū)別在那呢?static type認為,class就是type,type就是class; subclass就是subtyping,subtyping就是subclass(其實這句不嚴謹,在c++里可以使得subclass不是 subtyping,但是java里就沒辦法了);而dynamic type則認為類型和class沒有關系,類型取決于一個對象能夠接受的消息。

那么哪個才是面向對象之真貌呢?遺憾的說,static type并不是最初的面向對象。以對象作為模塊化的單位,始自Simula 67。但是Simula 67并不是一個面向對象系統(tǒng),以目前的觀點來看,充其量是Object-based,第一個面向對象語言當推Smalltalk,Smalltalk是 dynamic type的。不過Smalltalk不太流行,第一個大面積流行的面向對象語言是C++,C++是static type的,正如Lisp是第一個函數式編程語言,很多Lisp的特性被當作函數式語言的共有特性(比如表是最重要的數據結構,輕語法)一樣,所以很多人 以為面向對象就必然是static type(比如老莊和我)。對于面向對象的誤解,80%來自C++。也就是說,80%來自于static type的面向對象系統(tǒng)。將static type面向對象歸咎于整個面向對象,我輩實在是大而無當言過其實。

后面我再一一將老莊所言之OO不當之處加以說明

第1 關于"接口"

關于接口的問題老莊說對了,這個東西并不屬于面向對象的概念,而且在動態(tài)類型面向對象語言(比如Ruby, Smalltalk里),根本沒有這個東西。這是一個純粹的靜態(tài)類型面向對象語言的特性,或者直接說,接口就是一個純類型(Type)。還是上次的例子:

 1interface Instrument {
 2   void playNote(Note note);
 3   void playChord(Chord chord);
 4}
 5
 6in Person Class
 7
 8void playSolo(Instrument instrument) {
 9 
10}

在我接觸Smalltalk的最開始的一段時間里,這種地方是讓我最難受,我已經習慣了用類型輔助我的思維,但是我發(fā)現我在Smalltalk里做不到,雖然我可以寫出

Instrument>>playNote:note
  ^self subclassResponsibility.

Instrument>>playChord:chord
  ^self subclassResponsibility.

但是他卻不是一個接口,我可以很用

instrument = Instrument new.
instrument playNote: Note C.

來構造一個Instrument之后在它之上調用playNote方法,然而我會得到一個messageNotUnderstand的錯誤, Smalltalk和Ruby里沒有Abstract的概念。也就是說abstract method,abstract class以及interface,都不是面向對象的概念(或者嚴格一些說,都不是面向對象的必須的概念),而是面向對象類型系統(tǒng)的概念。那么在 Smalltalk里我們會怎么做呢?

Person>>playSoloOnInstrument:instrument
  instrument playNote: Note C;
             playNote: Note D;
             playNote: Note E.

Person>>playBackgroundOnInstrument:instrument
  instrument playChord: Chord C1;
                      playChord: Chord C1;
                      playChord: Chord C1;

對于playSoloOnInstrument:instrument,我們對于instrument的類型是有要求的,就是它必須能夠接受playNote這個消息。當然這個類型需要是隱性,我也可以對等的寫出靜態(tài)面向對象的代碼把這個隱性的類型顯示的表示出來:

1interface Instrument {
2   Instrument playNote(Note note);  
3}

同樣對于第二個方法我們也可以寫出來:

1interface Instrument {
2   Instrument playChord(Note note);  
3}

如果我們需要多于一個的消息也是一樣的,比如

Person>>playBWV996OnInstrument:instrument
   instrument playNote: Note C;
              playChord: Chord C;
              playNote: Note D.

同樣這個時候隱性的類型需要就是

1interface Instrument {
2   Instrument playNote(Note note);  
3   Instrument playChord(Note note);  
4}

那么接口是什么呢?我給出一個不確切的說法, interface是一個消息的發(fā)送者(sender)和一個消息的接受者(reciver)間的一種類型的約定 , 也就是說在我看來interface的用處主要在細粒度的顯式類型約定。我有一個同事,每次寫代碼都為一個Test Case所要測試的對象定義一個interface,每個interface都只有2-3個方法(lx同學夸你呢:D),這是很得interface之三 味的用法。這種的做法對于在靜態(tài)的面向對象系統(tǒng)的好處我們在繼承里再論述。

至于老莊所說的接口是多繼承的一種代替品,這只不過是世俗的看法,在靜態(tài)類型的面向對象里,繼承至少有2個語義:

1.實現繼承,這個在Smalltalk,Ruby,C++里有,而在java里沒有,C++里是通過private extends來實現的

1class SubClassA: private ImplementationParent {
2}

這也是C++里為數不多的subclass不是subtype的例子。

2.類型繼承,這個在C++和java里有,而在smalltalk,ruby有卻不明顯。

類型繼承的極致就是C++里的純虛父類

1abstract class Parent {
2
3  public asbtract void method1() = 0;
4  public asbtract void method2() = 0;
5}

也就是java里的interface

1interface Parent {
2   void method1();
3   void method2();
4}

因此,也就明了了,所謂“面向接口編程”是以類型作為約定的編程。我覺得這點大家一定不陌生,面向接口的編程里interface都很小而且約定明 確。但是要說明一點的是,這個東西和"面向抽象而不要面向具體編程"其實還不一樣,所以這個東西也就僅僅能算是靜態(tài)類型面向對象的一個慣用法,還到不了原 則這么高。

第2 繼承

前面已經說過了,繼承至少有2個語義: 實現繼承和類型繼承,在說明這兩個東西之前,我們繼續(xù)來看上面的例子

Person>>playSoloOnInstrument:instrument
  instrument playNote: Note C;
             playNote: Note D;
             playNote: Note E.

Person>>playBackgroundOnInstrument:instrument
  instrument playChord: Chord C1;
      playChord: Chord C1;
             playChord: Chord C1;

Person>>playBWV996OnInstrument:instrument
   instrument playNote: Note C;
              playChord: Chord C;
              playNote: Note D.

現在我們看playBWV996這個消息,BWV996是Bach所寫一個魯特琴組曲,魯特琴是彈撥樂器,同時也是和聲樂器(所謂和聲樂器就是可以演奏和聲)。在很多樂器上都有改編的版本,比如魯特琴的近親吉他等等,這個時候,我們可以實現這樣幾個類

Lute>>playNote:note
  
Lute>>playChord:note
  

Guitar>>playNote:note
  
Guitar>>playChord:note
  

Bass>>playNote:note
  

然后我們可以嘗試以此調用

vincent.playBWV996OnInstrument: Guitar new.
vincent.playBWV996OnInstrument: Lute new.
vincent.playBWV996OnInstrument: Bass new.

最后一個會得到一個messageNotUnderstand的錯誤。也就是說,對于Bass而言由于不能演奏和聲從而不能演奏BMV996(不過這個世界上能人太多了...哎),我們換到靜態(tài)類型面向對象系統(tǒng)來看。
對于第一個方法,playSolo的時候我們要求的類型是能夠演奏單音的。我們可以寫出來

1interface SoloInstrument {
2  SoloInstrument playNote(Note note);   
3}

對于第二個方法,playChord的時候我們要求的類型是能夠演奏和弦的,我們可以寫出來

1interface ChordInstrument {
2  ChordInstrument playChord(Chord note);   
3}

而對于第三個方法,playBWV996的時候我們要求既能演奏和弦也能演奏單音,這個時候出現一個問題,我們怎么處理Instrument的繼承關系?一個能演奏和弦的樂器是否可以演奏單音(答案是一般而言是的,但是也不排除有一些不是這樣的)?還是我們簡單的寫:

1interface SoloAndChordInstrument extends SoloInstrument, ChordInstrument{
2}

或者

1interface BWV996Playable {
2
3  BWV996Playable playNote(Note note); 
4  BWV996Playable playChord(Chord note);  
5}

對于動態(tài)類型簡單的隱性類型約定,顯示的類型系統(tǒng)帶來的一個副作用就是我們必須處理類型之間的關系。 注意這里是類型之間的關系,而不是對象之間的關系 。老莊同志批了很多篇的面向對象的抽象,面向對象的類型系統(tǒng)以及面向對象的本體論, 其實都在是在類型關系上折騰,而不是在對象關系上折騰 。而事實上面向對象的 類型系統(tǒng)并非必然就是靜態(tài)類型系統(tǒng),而我們的類之間的關系不一定就和類型的關系相一致。 就像上例所示,在Smalltalk里,Lute,Guitar和Bass之間沒有任何的繼承關系,但是對于person的3個消息而言,它們卻是有類型的。

因此老莊所批的,是對象類型系統(tǒng)的抽象能力,而非面向對象的抽象能力。正如他在類型系統(tǒng)里所給的例子,那張他認為很失敗的面向對象的圖,其實可以完全不依賴繼承來實現,而對這個類型系統(tǒng)的消費者而言,他們能夠以一定的類型的觀點,來處理這個系統(tǒng)的對象。

而老莊最后一個結論:

我的結論是:“一個類型,是由其本質決定了所能表現出的可操作性,而不是有其所能接受的操作決定了其本質。然而,OO正好把這個問題搞反了!”

我的看法是,這句話根本就是詭辯,前面半句的主語是“一個類型”,后面半句的主語是"OO"...

雖然前半句是對的,但是換一樣說法可能更好:" 所能接受的操作反映了其本質 ", 面向對象本身就沒有說我要做一個本質抽象,這一點在Smalltalk的類型判斷操作上的可能是一個佐證,Smalltalk用isKindOf來判斷繼 承關系,我們來玩一個文字游戲,改成俚語就是kinda,也就是"有一點,有幾分"的意思,而不是說,“就是”,或者“從分類學上可證明之類的含義”。我 再舉一個齷齪的例子。

vincent ballon: AirBallon new.
vincent ballon: Condom new.

氣球和保險套,對于ballon這個方法而言是一個類型,都是"有幾分"可以吹起來。但是我怎么定義一個精確的本質?Ballonable?還是MakeFromLatexAndVeryThin?或者簡單說FlexableAndThin?

在繼承這一點上,我想老莊引文中:Elminster的話是從事物的特征與屬性歸納出它的“類型”。恰恰對于靜態(tài)類型面向對象系統(tǒng)是可行的。如我前 文所述,我把一個object和所有sender的約定(也就是interface),繼承在一起,恰恰就是一個頗為恰當的類型定義。

而對于動態(tài)類型系統(tǒng)里的面向對象語言,繼承的也有類型繼承的含義,但是并不是唯一的途徑。用一句我們常說的話,在靜態(tài)類型系統(tǒng)里,類型和類是緊耦合的,動態(tài)類型系統(tǒng)中他們的耦合比較松。

從此而觀,所有對于面向對象的哲學考慮以及本體的思考,對于動態(tài)面向對象系統(tǒng)已經不是那么迫切了。而把對象類型系統(tǒng)的不足歸咎于面向對象的不足,也似乎論據不足。

第3. 一切皆對象和面向對象的理論基礎

老莊是反對一切皆對象的,而TrustNo1在javaeye的一篇帖子上說:

第一,我可以很負責的說,OO的,70年代成型,80年代在理論基礎上就給人斃掉。從這種意義上說不是OO死不死的問題,而是OO還活著么?當然理論基礎給人斃掉,不是說沒有用。

我先說面向對象的理論基礎的問題,至于一切皆對象稍后再表。

所謂面向對象的理論基礎其實是沒有的,原因很簡單,面向對象根本就不是 一種計算模型。在第一次軟件危機的那個時代,對與計算機的非數值計算應用的討論以及對于可計算性問題的研究和發(fā)展,大抵確立了幾種主流的計算模型:遞歸函 數類,圖靈機,Lambda演算,Horn子句,Post系統(tǒng)等等。

其中遞歸函數類是可計算性問題的數學解釋;圖靈機是圖靈解決可計算問 題的時候所設計的裝置,其后成為計算機的裝置模型,與圖靈機相關的形式語言和自動機成為了命令式語言的理論基礎;lambda演算成為了函數式語言的理論 基礎;Horn子句是prolog這類邏輯語言的理論基礎。但是我們驚訝的發(fā)現,面向對象沒有計算模型的理論基礎,換而言之,面向對象根本就不是從可計算 性的研究上發(fā)展過來的,那么面向對象的理論基礎的價值本身就不大。

所以我很奇怪的一個問題就是TrustNo1所謂的面向對象在80年代理論基礎上給人斃掉的說法是從何而來的?既然面向對象本質上不是一種計算模 型,那么它大抵上只能歸結為一種應用技術,應用技術自然可以從各種不同的領域里得到相似的應用,那么斃掉的理論基礎所指的又是什么呢?甚怪之。

既然面向對象不是一個計算模型,那么我們可以從不同的角度推斷出OO的各種形態(tài),老莊已經出給了從ADT引出OO的問題以及例子,我就不羅嗦了,我 給一個從Functional Programming出來的例子,其實就是SICP里的Data as Procedure。

(define (make-user name age sex)
  (define (dispatch message)
     (cond ((eq? message 'getName) name)
           ((eq? message 'getAge) age)
           ((eq? message 'getSex) sex))
           (else (error 'messageNotUnderstand))))
  dispatch)

然后我們就可以

(define vincent (make-user 'Vincent 24 'Male))
(vincent 'getName)

自然的,如果我調用

(vincent 'sayHi)

會得到一個messageNotUnderstand的runtime錯誤,這就是一個很自然dyanmic type的對象封裝,最早的面向對象系統(tǒng)Smalltalk和CLOS基本上都是這個路子,于是有一個問題,為什么最早的面向對象系統(tǒng)都是dyanmic type?這里就跟lambda演算有關了。

lambda演算這個計算模型根本的一個假設就是,對于任何一個定義良好的數學函數,我都可以使用lambda抽象來表述他的求值,因此無論是什么 東西你能夠構造lambda抽象的話,我就能計算。這個地方東西很多,大家可以找找lambda演算相關的資料,這里我說三件事(由于lambda太難輸 入,我用scheme程序代替,然后由于alpha變化,beta規(guī)約和eta規(guī)約我也用scheme偽碼來模擬。)

第一個是數值的表述,其實這個很簡單,不考慮丘奇代數的系統(tǒng)的話,我們可以把數值表示成單值函數:

(define one (lambda (x) 1))

這個東西無論給什么x都返回1,然后根據lambda演算里的alpha變換,這個lambda抽象等價于數值1。因此,對于所有的數值,我們可以按lambda演算處理。

第二個是bool的表達,也就是如何邏輯進行l(wèi)ambda抽象,下面我直接給出了,缺省認為大家都看了SICP,對Scheme也頗有心得。

(define true-new (lambda (x y) x)) ;;;這個函數也叫select-first
(define false-new (lambda (x y) x));;;這個函數也叫select-second

(define if-new (lambda (conditon if-true if-false) (condition if-true if-false)))

然后我就可以做一個測試

(if-new true-new 3 4)
3

(if-new false-new 3 4)
4

因此,對于所有bool我們可以按lambda演算來處理

第三個是自定義類型,這里我們還是先看一個Lisp里的例子,序對。

(define (cons a b) (lambda (dispath) (dispatch a b)))
(define (car list) (list select-first))
(define (cdr list) (list select-second))

這里依舊是high-order,我們來測試

(define list1 (cons 1 2))
(car list1)
1
(cdr list1)
2

這里大家自己用beta規(guī)約算一下,就發(fā)現的確是這樣的。這里我們又可以看到,在lambda演算里,根本沒有數據或者類型。有的永遠各種各樣的 lambda抽象而已(目前已經有了帶類型的lambda演算)。這里說一句題外話,SICP里的Data as Procedure其實就是在說這個問題,不過他沒明說,而是用了一種特殊的用法而引出了消息傳遞風格,我覺得這里SICP有些顧此失彼,對于data as procedure我總結的一般形式是

(define (construct-function value1 value2 value3 value4valuen) (lambda (dispatch) (dispatch value1 value2 value3 value4valuen)))
(define (select-function1 data) (data select-first))
(define (select-function2 data) (data select-second))
.
(define (select-functionn data) (data select-last))

綜上所述,我們看到在lambda演算里,一切都是lambda抽象,然后對于不同的lambda抽象使用alpha變換,beta規(guī)約和eta規(guī)約,表述各種不同計算。看,在面向對象之前就已經有了一切皆某某的完美的計算理論存在了。而且回顧一下:

(define (make-user name age sex)
  (define (dispatch message)
     (cond ((eq? message 'getName) name)
           ((eq? message 'getAge) age)
           ((eq? message 'getSex) sex))
           (else (error 'messageNotUnderstand))))
  dispatch)

(define vincent (make-user 'Vincent 24 'Male))
(vincent 'getName)

我們有理由說,對象其實就是一個lambda抽象,所以一切皆對象不過是一切皆lambda抽象的演化,這也是為什么SICP里把面向對象稱作一種“方便的界面”而不是一種抽象的方法的原因了。那么對象和lambda抽象又什么區(qū)別呢?

嘿 嘿,熟悉FP的人都應該知道了,就是Side-Effect,副作用。對象允許對其內部狀態(tài)進行修改,那么這個東西就破化了eta規(guī)約的前提條件,也就是 說允許修改內部狀態(tài)的東西,已經不是一個可以進行l(wèi)ambda計算的lambda抽象了。因此暫且給一個別的名字吧,就叫對象吧.....因此我認為,對 象很大程度上是一種帶有副作用的lambda抽象。

我在有一篇blog上寫了Say sorry to object-oriented,里面給了一只用對象作分支的例子,這里就不重復了,有興趣大家可以去看一下(剛才好像在JavaEye上看到一個說法, 說Everything is Object是Smalltalk的廣告語,唉,Smalltalk里的的的確確everything is object啊。)

這里我們來總結一下,面向對象作為一種“方便的界面”主要解決了一個局部化和模塊化的問題,這是從lambda演算和 函數編程的角度來看面向對象技術。(taowen在他的一篇blog上說,面向對象局部化了Side-Effect,我深以為然),這個東西我個人認為更 加接近面向對象本來的意思,而不是由ADT里發(fā)展出來的帶類型的對象系統(tǒng)的那個意思。因此老莊不以為然的面向對象類型系統(tǒng),我也不以為然。但是面向對象作 為lambda抽象的界面,我覺得還是很不錯的。這一點在Smalltalk和Ruby里都有不錯的體現。


posted on 2008-06-14 14:26 cuigang 閱讀(224) 評論(0)  編輯 收藏 引用 所屬分類: 轉帖

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            99国产精品| 99pao成人国产永久免费视频| 99亚洲一区二区| 国产精品午夜在线| 久久久久久伊人| 欧美成人午夜视频| 亚洲免费视频成人| 久久综合久久综合久久综合| 日韩亚洲一区在线播放| 久久国产精品久久精品国产| 亚洲国产乱码最新视频| 中文在线不卡| 日韩亚洲综合在线| 久久精品国产久精国产一老狼 | 亚洲一区二区视频| 99精品免费视频| 久久综合网色—综合色88| 性欧美办公室18xxxxhd| 欧美日韩国产综合视频在线观看中文 | 亚洲视频你懂的| 99在线|亚洲一区二区| 欧美国产精品一区| 欧美国产高潮xxxx1819| 在线免费不卡视频| 一区二区三区久久精品| 久久精品国产亚洲aⅴ| 久久精品人人做人人爽电影蜜月| 欧美性淫爽ww久久久久无| 亚洲国产精品第一区二区| 亚洲经典在线看| 欧美高清在线播放| 亚洲国产精品99久久久久久久久| 在线观看国产成人av片| 欧美精品久久99久久在免费线| 亚洲第一黄色网| 中文精品视频一区二区在线观看| 欧美人与禽猛交乱配视频| 一本一本久久a久久精品综合妖精| 亚洲欧美在线免费观看| 狠狠色丁香婷婷综合影院| 欧美成人免费在线观看| 午夜精品久久久久久久| 欧美www视频在线观看| 一区二区三区四区国产| 国产一区二区中文字幕免费看| 毛片精品免费在线观看| 亚洲欧美日韩精品一区二区 | 欧美在线精品免播放器视频| 亚洲国产综合91精品麻豆| 亚洲夜间福利| 亚洲欧洲一区二区三区久久| 国产精品久久9| 欧美福利视频在线| 欧美专区在线| 亚洲一区3d动漫同人无遮挡| 亚洲国产精品成人精品| 久久天天躁狠狠躁夜夜av| 亚洲摸下面视频| 亚洲综合大片69999| 一本不卡影院| 日韩一级大片| 欧美大片一区二区| 久久精品中文| 久久久久免费视频| 久久久久9999亚洲精品| 欧美主播一区二区三区| 亚洲男女自偷自拍| 午夜精品区一区二区三| 午夜视频一区在线观看| 午夜一区在线| 久久青草福利网站| 欧美精品日韩三级| 国产精品久久99| 精品电影在线观看| 亚洲免费成人av电影| 中文在线一区| 毛片一区二区| 一区二区高清视频| 亚洲国产婷婷| 欧美一级视频| 亚洲电影在线| 篠田优中文在线播放第一区| 欧美福利一区| 韩国三级在线一区| 亚洲视频在线播放| 亚洲第一在线综合在线| 亚洲女爱视频在线| 欧美日韩ab片| 亚洲激情黄色| 麻豆国产精品777777在线| 亚洲午夜精品国产| 欧美日韩免费观看中文| 狠狠色丁香久久婷婷综合丁香| 亚洲制服丝袜在线| 亚洲人成人99网站| 蜜臀av在线播放一区二区三区| 欧美午夜激情小视频| 日韩亚洲精品在线| 亚洲高清激情| 欧美第一黄网免费网站| 亚洲黄色免费| 亚洲精品美女久久7777777| 免费看精品久久片| 亚洲每日更新| 亚洲深夜福利网站| 亚洲国产婷婷| 欧美精品日韩www.p站| 在线视频精品一| 一区二区三区四区五区在线| 欧美日韩亚洲另类| 性感少妇一区| 老司机午夜精品视频| 亚洲日本欧美日韩高观看| 亚洲日韩视频| 国产日韩精品一区| 免费人成网站在线观看欧美高清| 久久久青草婷婷精品综合日韩| 亚洲欧洲日本专区| 一个人看的www久久| 在线精品亚洲| 一区二区激情小说| 一区二区三区中文在线观看| 亚洲国产成人不卡| 国产欧美日韩三级| 日韩视频在线播放| 国产综合香蕉五月婷在线| 亚洲国产精品久久久久| 国产精品色婷婷久久58| 亚洲福利视频在线| 国产色产综合产在线视频| 亚洲高清免费| 精品成人a区在线观看| 一区二区冒白浆视频| 亚洲激情视频网| 久久久亚洲高清| 美女性感视频久久久| 国产一区成人| 久久精品色图| 免费在线国产精品| 国产精品天天看| 极品尤物一区二区三区| 亚洲欧美日韩精品久久| 羞羞答答国产精品www一本| 欧美片第1页综合| 亚洲精品久久7777| 中文欧美在线视频| 欧美精品一区视频| 日韩视频国产视频| 欧美一区二区日韩一区二区| 国产精品亚洲人在线观看| 午夜精品久久久久久久久久久久久| 国产精品久久久久av免费| 久久精品人人做人人爽| 亚洲欧美激情视频| 91久久在线播放| 欧美福利电影网| 牛牛影视久久网| 欧美va亚洲va国产综合| 亚洲欧美国产视频| 一区二区在线观看视频在线观看| 欧美福利一区| 久久成人亚洲| 日韩视频中文| 亚洲第一免费播放区| 欧美一区亚洲二区| 99国产精品| 亚洲精品国产精品国自产观看| 国产欧美1区2区3区| 欧美激情第10页| 麻豆国产精品777777在线| 午夜日本精品| 欧美一区日本一区韩国一区| 日韩视频一区二区三区| 美女视频黄a大片欧美| 欧美.日韩.国产.一区.二区| 免费观看日韩av| 最近中文字幕日韩精品| 日韩一级在线观看| 一区二区三区精品在线| 欧美亚洲三区| 久久久久一区二区| 欧美不卡视频| 国产伦精品一区二区三区照片91| 欧美日韩在线播放三区| 国产精品欧美激情| 激情综合网址| 亚洲综合色在线| 老司机凹凸av亚洲导航| 亚洲国产精品一区二区第一页| 亚洲精品一区二区三区福利| 亚洲欧美日韩精品久久亚洲区| 久久精品国产欧美激情| 欧美成人一区二区在线| 国内精品视频在线观看| 亚洲网站视频福利| 欧美激情精品久久久久久蜜臀| 午夜影院日韩| 亚洲欧洲一区二区天堂久久| 久久婷婷蜜乳一本欲蜜臀| 久久国产精品久久久久久电车|