精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

從Java走進Scala:當繼承中的對象遇到函數

開發 后端
Scala 對實現繼承的支持與 Java 語言一樣豐富 —— 但 Scala 的繼承帶來了一些驚喜。本文中,Ted Neward 介紹了以 Scala 方式完成的多態,還介紹了混合函數與面向對象的語言風格,同時使您依然能夠完美地映射到 Java 平臺的繼承模型。

近十幾年來,面向對象語言設計的要素一直是繼承的核心。不支持繼承的語言(如 Visual Basic)被嘲諷是 “玩具語言” ,不適合真正的工作。與此同時,支持繼承的語言所采用的支持方法五花八門,導致了許多爭論。多重繼承是否真的必不可少(就像 C++ 的創作者認定的那樣),它是否不必要而丑陋的(就像 C# 和 Java 的創作者堅信的那樣)?Ruby 和 Scala 是兩種較新的語言,采取了多重繼承的這種方法 — 正如我在上期介紹 Scala 的特征時所討論的那樣。

與所有 杰出的語言一樣,Scala 也支持實現繼承。在 Java 語言中,單一實現繼承模型允許您擴展基類,添加新方法和字段等。盡管存在某些句法變更,Scala 的實現繼承依然類似于 Java 語言中的實現。不同的是 Scala 融合了對象和函數語言設計,這非常值得我們在本期文章中進行討論。

普通 Scala 對象

與本系列之前的文章類似,我將使用 Person 類作為起點,探索 Scala 的繼承系統。清單 1 展示了 Person 的類定義:

清單 1. 嘿,我是人類

  1. // This is Scala  
  2. class Person(val firstName:String, val lastName:String, val age:Int)  
  3. {  
  4.   def toString = "[Person: firstName="+firstName+" lastName="+lastName+  
  5.                          " age="+age+"]" 

Person 是一個非常簡單的 POSO(普通 Scala 對象,Plain Old Scala Object),具有三個只讀字段。您可能會想起,要使這些字段可以讀寫,只需將主構造函數聲明中的 val 更改為 var 即可

無論如何,使用 Person 類型也非常簡單,如清單 2 所示:

清單 2. PersonApp

  1. // This is Scala  
  2. object PersonApp  
  3. {  
  4.   def main(args : Array[String]) : Unit =  
  5.   {  
  6.     val bindi = new Person("Tabinda""Khan"38)  
  7.     System.out.println(bindi)  
  8.   }  

這算不上什么令人驚訝的代碼,但給我們提供了一個起點。

Scala 中的抽象方法

隨著該系統的發展,越來越明顯地意識到 Person 類缺乏一個成為 Person 的重要部分,這個部分是做些事情 的行為。許多人都會根據我們在生活中的作為來定義自己,而不是根據現有和占用的空間。因此,我會添加一個新方法,如清單 3 所示,這賦予了 Person 一些意義:

清單 3. 很好,做些事情!

  1. // This is Scala  
  2. class Person(val firstName:String, val lastName:String, val age:Int)  
  3. {  
  4.   override def toString = "[Person: firstName="+firstName+" lastName="+lastName+  
  5.                           " age="+age+"]" 
  6.  
  7.   def doSomething = // uh.... what?  
  8. }  

這帶來了一個問題:Person 的用途究竟是什么?有些 Person 繪畫,有些唱歌,有些編寫代碼,有些玩視頻游戲,有些什么也不做(問問十幾歲青少年的父母)。因此,我會為 Person 創建 子類,而不是嘗試去將這些活動直接整合到 Person 本身之中,如清單 4 所示:

清單 4. 這個人做的事情很少

  1. // This is Scala  
  2. class Person(val firstName:String, val lastName:String, val age:Int)  
  3. {  
  4.   override def toString = "[Person: firstName="+firstName+" lastName="+lastName+  
  5.                           " age="+age+"]" 
  6.  
  7.   def doSomething = // uh.... what?  
  8. }  
  9.  
  10. class Student(firstName:String, lastName:String, age:Int)  
  11.   extends Person(firstName, lastName, age)  
  12. {  
  13.   def doSomething =  
  14.   {  
  15.     System.out.println("I'm studying hard, Ma, I swear! (Pass the beer, guys!)")  
  16.   }  
  17. }  

當嘗試編譯代碼時,我發現無法編譯。這是因為 Person.doSomething 方法的定義無法工作;這個方法需要一個完整的主體(或許可拋出異常來表示它應在繼承類中被覆蓋),或者不需要主體,類似于 Java 代碼中抽象方法的工作方式。我在清單 5 中嘗試使用抽象的方法:

清單 5. 抽象類 Person

  1. // This is Scala  
  2. abstract class Person(val firstName:String, val lastName:String, val age:Int)  
  3. {  
  4.   override def toString = "[Person: firstName="+firstName+" lastName="+lastName+  
  5.                           " age="+age+"]" 
  6.  
  7.   def doSomething; // note the semicolon, which is still optional  
  8.                    // but stylistically I like having it here  
  9. }  
  10.  
  11. class Student(firstName:String, lastName:String, age:Int)  
  12.   extends Person(firstName, lastName, age)  
  13. {  
  14.   def doSomething =  
  15.   {  
  16.     System.out.println("I'm studying hard, Ma, I swear! (Pass the beer, guys!)")  
  17.   }  
  18. }  

請注意,我如何使用 abstract 關鍵字裝飾 Person 類。abstract 為編譯器指出,是的,這個類應該是抽象的。在這方面,Scala 與 Java 語言沒有區別。

#p#

對象,遇到函數

由于 Scala 融合了對象和函數語言風格,我實際上建模了 Person(如上所述),但并未創建子類型。這有些古怪,但強調了 Scala 對于這兩種設計風格的整合,以及隨之而來的有趣理念。

回憶 前幾期文章,Scala 將函數作為值處理,就像處理語言中的其他值一樣,例如 Int、Float 或 Double。在建模 Person 時,我可以利用這一點來獲得 doSomething,不僅將其作為一種繼承類中覆蓋的方法,還將其作為可調用、替換、擴展的 函數值。清單 6 展示了這種方法:

清單 6. 努力工作的人

  1. // This is Scala      
  2. class Person(val firstName:String, val lastName:String, val age:Int)  
  3. {  
  4.   var doSomething : (Person) => Unit =   
  5.     (p:Person) => System.out.println("I'm " + p + " and I don't do anything yet!");  
  6.       
  7.   def work() =  
  8.     doSomething(this)  
  9.       
  10.   override def toString = "[Person: firstName="+firstName+" lastName="+lastName+  
  11.                           " age="+age+"]" 
  12. }  
  13.  
  14. object App  
  15. {  
  16.   def main(args : Array[String]) =  
  17.   {  
  18.     val bindi = new Person("Tabinda""Khan"38)  
  19.     System.out.println(bindi)  
  20.       
  21.     bindi.work()  
  22.       
  23.     bindi.doSomething =  
  24.       (p:Person) => System.out.println("I edit textbooks")  
  25.         
  26.     bindi.work()  
  27.       
  28.     bindi.doSomething =  
  29.       (p:Person) => System.out.println("I write HTML books")  
  30.         
  31.     bindi.work()  
  32.   }  
  33. }  

將函數作為***建模工具是 Ruby、Groovy 和 ECMAScript(也就是 JavaScript)等動態語言以及許多函數語言的常用技巧。盡管其他語言也可以用函數作為建模工具,(C++ 通過函數指針和/或成員函數指針實現,Java 代碼中通過接口引用的匿名內部類實現),但所需的工作比 Scala(以及 Ruby、Groovy、ECMAScript 和其他語言)多得多。這是函數語言使用的 “高階函數” 概念的擴展。(關于高階函數的更多內容,請參見 參考資料。)

多虧 Scala 將函數視為值,這樣您就可以在運行時需要切換功能的時候利用函數值。可將這種方法視為角色模式 —— Gang of Four 戰略模式的一種變體,在這種模式中,對象角色(例如 Person 的當前就職狀態)作為運行時值得到了更好的表現,比靜態類型的層次結構更好。

層次結構上層的構造函數

回憶一下編寫 Java 代碼的日子,有時繼承類需要從構造函數傳遞參數至基類構造函數,從而使基類字段能夠初始化。在 Scala 中,由于主構造函數出現在類聲明中,不再是類的 “傳統” 成員,因而將參數傳遞到基類將成為一個全新維度的問題。

在 Scala 中,主構造函數的參數在 class 行傳遞,但您也可以為這些參數使用 val 修飾符,以便在類本身上輕松引入讀值器(對于 var,則為寫值器)。

因此,清單 5 中的 Scala 類 Person 轉變為清單 7 中的 Java 類,使用 javap 查看:

清單 7. 請翻譯一下

  1. // This is javap  
  2. C:\Projects\scala-inheritance\code>javap -classpath classes Person  
  3. Compiled from "person.scala" 
  4. public abstract class Person extends java.lang.Object implements scala.ScalaObje  
  5. ct{  
  6.     public Person(java.lang.String, java.lang.String, int);  
  7.     public java.lang.String toString();  
  8.     public abstract void doSomething();  
  9.     public int age();  
  10.     public java.lang.String lastName();  
  11.     public java.lang.String firstName();  
  12.     public int $tag();  
  13. }      

JVM 的基本規則依然有效:Person 的繼承類在構造時向基類傳遞某些內容,而不管語言強調的是什么。(實際上,這并非完全 正確,但在語言嘗試規避此規則時,JVM 會表現失常,因此大多數語言仍然堅持通過某種方法為其提供支持。)當然,Scala 需要堅守此規則,因為它不僅需要保持 JVM 正常運作,而且還要保持 Java 基類正常運作。這也就是說,無論如何,Scala 必須實現一種語法,允許繼承類調用基類,同時保留允許我們在基類上引入讀值器和寫值器的語法。

為了將此放到更具體的上下文中,假設我通過以下方式編寫了 清單 5 中的 Student 類:

清單 8. 壞學生!

  1. // This is Scala  
  2. // This WILL NOT compile  
  3. class Student(val firstName:String, val lastName:String, val age:Int)  
  4.   extends Person(firstName, lastName, age)  
  5. {  
  6.   def doSomething =  
  7.   {  
  8.     System.out.println("I'm studying hard, Ma, I swear! (Pass the beer, guys!)")  
  9.   }  

本例中的編譯器將運行很長一段時間,因為我嘗試為 Student 類引入一組新方法(firstName、lastName 和 age)。這些方法將與 Person 類上名稱類似的方法彼此沖突,Scala 編譯器不一定了解我是否正在嘗試覆蓋基類方法(這很糟糕,因為我可以在這些基類方法后隱藏實現和字段),或者引入相同名稱的新方法(這也很糟糕,因為我可以在這些基類方法后隱藏實現和字段)。簡而言之,您將看到如何成功覆蓋來自基類的方法,但那并不是我們目前要追求的目標。

您還應注意到,在 Scala 中,Person 構造函數的參數不必一對一地與傳遞給 Student 的參數聯系起來;這里的規則實際上與 Java 構造函數的規則完全相同。我們這樣做只是為了便于閱讀。同樣,Student 可要求額外的構造函數參數,與在 Java 語言中一樣,如清單 9 所示:

清單 9. 苛求的學生!

  1. // This is Scala  
  2. class Student(firstName:String, lastName:String, age:Int, val subject:String)  
  3.   extends Person(firstName, lastName, age)  
  4. {  
  5.   def doSomething =  
  6.   {  
  7.     System.out.println("I'm studying hard, Ma, I swear! (Pass the beer, guys!)")  
  8.   }  

您又一次看到了 Scala 代碼與 Java 代碼有多么的相似,至少涉及繼承和類關系時是這樣。

語法差異

至此,您可能會對語法的細節感到迷惑。畢竟 Scala 并未像 Java 語言那樣將字段與方法區分開來。這實際上是一項深思熟慮的設計決策,允許 Scala 程序員輕而易舉地向使用基類的用戶 “隱藏” 字段和方法之間的差異。考慮清單 10:

清單 10. 我是什么?

  1. // This is Scala  
  2. abstract class Person(val firstName:String, val lastName:String, val age:Int)  
  3. {  
  4.   def doSomething  
  5.     
  6.   def weight : Int  
  7.       
  8.   override def toString = "[Person: firstName="+firstName+" lastName="+lastName+  
  9.                           " age="+age+"]" 
  10. }  
  11.  
  12. class Student(firstName:String, lastName:String, age:Int, val subject:String)  
  13.   extends Person(firstName, lastName, age)  
  14. {  
  15.   def weight : Int =  
  16.     age // students are notoriously skinny  
  17.  
  18.   def doSomething =  
  19.   {  
  20.     System.out.println("I'm studying hard, Ma, I swear! (Pass the beer, guys!)")  
  21.   }  
  22. }  
  23.  
  24. class Employee(firstName:String, lastName:String, age:Int)  
  25.   extends Person(firstName, lastName, age)  
  26. {  
  27.   val weight : Int = age * 4 // Employees are not skinny at all  
  28.  
  29.   def doSomething =  
  30.   {  
  31.     System.out.println("I'm working hard, hon, I swear! (Pass the beer, guys!)")  
  32.   }  
  33. }  

注意查看如何定義 weight 使其不帶有任何參數并返回 Int。這是 “無參數方法”。因為它看上去與 Java 語言中的 “專有” 方法極其相似,Scala 實際上允許將 weight 定義為一種方法(如 Student 中所示),也允許將其定義為字段/存取器(如 Employee 中所示)。這種句法決策使您在抽象類繼承的實現方面有一定的靈活性。請注意,在 Java 中,即便是在同一個類中,只有通過 get/set 方法來訪問各字段時,才能獲得類似的靈活性。不知道判斷正確與否,但我認為只有少數 Java 程序員會用這種方式編寫代碼,因此不經常使用靈活性。此外,Scala 的方法可像處理公共成員一樣輕松地處理隱藏/私有成員。

#p#

從 @Override 到 override

繼承類經常需要更改在其某個基類內定義的方法的行為;在 Java 代碼中,我們通過為繼承類添加相同名稱、相同簽名的新方法來處理這個問題。這種方法的缺點在于簽名錄入的錯誤或含糊不清可能會導致沒有征兆的故障,這也就意味著代碼可以編譯,但在運行時無法正確完成操作。

為解決這個問題,Java 5 編譯器引入了 @Override 注釋。@Override 驗證引入繼承類的方法實際上已經覆蓋了基類方法。在 Scala 中,override 已經成為語言的一部分,幾乎可以忘記它會生成編譯器錯誤。因而,繼承 toString() 方法應如清單 11 所示:

清單 11. 這是繼承的結果

  1. // This is Scala  
  2. class Student(firstName:String, lastName:String, age:Int, val subject:String)  
  3.   extends Person(firstName, lastName, age)  
  4. {  
  5.   def weight : Int =  
  6.     age // students are notoriously skinny  
  7.  
  8.   def doSomething =  
  9.   {  
  10.     System.out.println("I'm studying hard, Ma, I swear! (Pass the beer, guys!)")  
  11.   }  
  12.     
  13.   override def toString = "[Student: firstName="+firstName+  
  14.                           " lastName="+lastName+" age="+age+  
  15.                           " subject="+subject+"]" 
  16. }  

非常簡單明了。

敲定

當然,允許繼承覆蓋的反面就是采取措施防止它:基類需要禁止子類更改其基類行為,或禁止任何類型的繼承類。在 Java 語言中,我們通過為方法應用修飾符 final 來實現這一點,確保它不會被覆蓋。此外,也可以為類整體應用 final,防止繼承。實現層次結構在 Scala 中的效果是相同的:我們可以向方法應用 final 來防止子類覆蓋它,也可應用于類聲明本身來防止繼承。

牢記,所有這些關于 abstract、final 和 override 的討論都同樣適用于 “名字很有趣的方法”(Java 或 C# 或 C++ 程序員可能會這樣稱呼運算符),與應用于常規名稱方法的效果相同。因此,我們常常會定義一個基類或特征,為數學函數設定某些預期(可以稱之為 “Mathable”),這些函數定義抽象成員函數 “+”、“-”、“*” 和 “/”,另外還有其他一些應該支持的數學運算,例如 pow 或 abs。隨后,其他程序員可創建其他類型 — 可能是一個 Matrix 類,實現或擴展 “Mathable”,定義一些成員,看上去就像 Scala 以開箱即用的方式提供的內置算術類型。

差別在于……

如果 Scala 能夠如此輕松地映射到 Java 繼承模型(就像本文至此您看到的那樣),就應該能夠從 Java 語言繼承 Scala 類,或反之。實際上,這必須 可行,因為 Scala 與其他編譯為 Java 字節碼的語言相似,必須生成繼承自 java.lang.Object 的對象。請注意,Scala 類可能也要繼承自其他內容,例如特征,因此實際繼承的解析和代碼生成的工作方式可能有所不同,但最終我們必須能夠以某種形式繼承 Java 基類。(切記,特征類似于有行為的接口,Scala 編譯器將特征分成接口并將實現推入特征編譯的目標類中,通過這種方式來使之運作。)

但結果表明,Scala 的類型層次結構與 Java 語言中的對應結構略有不同;從技術上來講,所有 Scala 類繼承的基類(包括 Int、Float、Double 和其他數字類型)都是 scala.Any 類型,這定義了一組核心方法,可在 Scala 內的任意類型上使用:==、!=、equals、hashCode、toString、isInstanceOf 和 asInstanceOf,大多數方法通過名稱即可輕松理解。在這里,Scala 劃分為兩大分支,“原語類型” 繼承自 scala.AnyVal;“類類型” 繼承自 scala.AnyRe。(scala.ScalaObject 又繼承自 scala.AnyRef。)

通常,這并不是您要直接去操心的方面,但在考慮跨兩種語言的繼承時,可能會帶來某些非常有趣的副作用。例如,考慮清單 12 中的 ScalaJavaPerson:

清單 12. 混合!

  1.   // This is Scala  
  2. ass ScalaJavaPerson(firstName:String, lastName:String, age:Int)  
  3. extends JavaPerson(firstName, lastName, age)  
  4.  
  5. val weight : Int = age * 2 // Who knows what Scala/Java people weigh?  
  6.  
  7. override def toString = "[SJPerson: firstName="+firstName+  
  8.                         " lastName="+lastName+" age="+age+"]" 

……它繼承自 JavaPerson:

清單 13. 看起來是否眼熟?

  1.     // This is Java  
  2. public class JavaPerson  
  3. {  
  4.     public JavaPerson(String firstName, String lastName, int age)  
  5.     {  
  6.         this.firstName = firstName;  
  7.         this.lastName = lastName;  
  8.         this.age = age;  
  9.     }  
  10.       
  11.     public String getFirstName()  
  12.     {  
  13.         return this.firstName;  
  14.     }  
  15.     public void setFirstName(String value)  
  16.     {  
  17.         this.firstName = value;  
  18.     }  
  19.       
  20.     public String getLastName()  
  21.     {  
  22.         return this.lastName;  
  23.     }  
  24.     public void setLastName(String value)  
  25.     {  
  26.         this.lastName = value;  
  27.     }  
  28.       
  29.     public int getAge()  
  30.     {  
  31.         return this.age;  
  32.     }  
  33.     public void setAge(int value)  
  34.     {  
  35.         this.age = value;  
  36.     }  
  37.       
  38.     public String toString()  
  39.     {  
  40.         return "[Person: firstName" + firstName + " lastName:" + lastName +  
  41.             " age:" + age + " ]";  
  42.     }  
  43.       
  44.     private String firstName;  
  45.     private String lastName;  
  46.     private int age;  
  47. }  

在編譯 ScalaJavaPerson 時,它將照常擴展 JavaPerson,但按照 Scala 的要求,它還會實現 ScalaObject 接口。并照例支持繼承自 JavaPerson 的方法,因為 ScalaJavaPerson 是一種 Scala 類型,我們可以期望它支持 Any 引用的指派,根據 Scala 的規則:

清單 14. 使用 ScalaJavaPerson

  1. // This is Scala      
  2. val richard = new ScalaJavaPerson("Richard""Campbell"45)  
  3. System.out.println(richard)  
  4. val host : Any = richard  
  5. System.out.println(host) 

但在 Scala 中創建 JavaPerson 并將其指派給 Any 引用時會發生什么?

清單 15. 使用 JavaPerson

  1. // This is Scala      
  2.     val carl = new JavaPerson("Carl""Franklin"35)  
  3.     System.out.println(carl)  
  4.     val host2 : Any = carl  
  5.     System.out.println(host2) 

結果顯示,這段代碼如期編譯并運行,因為 Scala 能確保 JavaPerson “做正確的事情”,這要歸功于 Any 類型與 java.lang.Object 類型的相似性。實際上,幾乎可以說,所有擴展 java.lang.Object 的內容都支持存儲到 Any 引用之中。(存在一些極端情況,我聽說過,但我自己還從未遇到過這樣的極端情況。)

最終結果?出于實踐的目的,我們可以跨 Java 語言和 Scala 混搭繼承,而無需過分擔心。(***的麻煩將是試圖了解如何覆蓋 “名字很有趣的 Scala 方法”,例如 ^=!# 或類似方法。)

結束語

在本月的文章中,我為您介紹了 Scala 代碼和 Java 代碼之間的高度相似性意味著 Java 開發人員可以輕松理解并使用 Scala 的繼承模型。方法覆蓋的工作方式相同,成員可見性的工作方式相同,還有更多相同的地方。對于 Scala 中的所有功能,繼承或許與 Java 開發中的對應部分最為相似。惟一需要技巧的部分就是 Scala 語法,這有著明顯的差異。

習慣兩種語言中繼承方法的相似之處和細微的差異,您就可以輕松編寫您自己的 Java 程序的 Scala 實現。例如,考慮流行的 Java 基類和框架的 Scala 實現,如 JUnit、Servlets、Swing 或 SWT。實際上,Scala 團隊已經提供了一個 Swing 應用程序,名為 OOPScala(參見 參考資料),它使用 JTable,通過相當少的幾行代碼(數量級遠遠低于傳統 Java 的對應實現)提供了簡單的電子表格功能。

因此,如果您想知道如何在您的生產代碼中應用 Scala,就應該準備好邁出探索的***步。考慮在 Scala 中編寫下一個程序的一小部分。正如您在這期文章中所了解到的那樣,從恰當的基類繼承,采用與 Java 程序中相同的方式提供覆蓋,您就不會遇到任何麻煩。

【相關閱讀】

  1. Scala編程語言專題
  2. 面向Java開發人員的Scala指南:使用Scala版本的Java接口
  3. 面向Java開發人員的Scala指南:Scala控制結構內部揭密
  4. 面向Java開發人員的Scala指南:理解Scala的類語法和語義
  5. 面向Java開發人員的Scala指南:面向對象的函數編程
責任編輯:yangsai 來源: IBMDW
相關推薦

2009-06-16 17:09:17

Scala面向對象函數編程

2009-09-28 11:01:39

從Java走進Scal

2009-08-21 16:17:25

ScalaTwitter API

2009-12-09 09:15:47

從Java走進ScalTwitter API

2009-06-17 11:44:22

Scala控制結構

2009-10-14 11:14:38

ScitterScalaTwitter

2009-06-16 17:54:38

Scala類語法語義

2009-07-15 10:14:25

Scala并發性

2009-02-04 17:32:03

ibmdwJavaScala

2009-06-17 13:57:25

Scala元組數組

2009-06-19 10:51:39

Scalapackage訪問修飾符

2009-08-14 11:35:01

Scala Actor

2011-04-12 11:34:17

友元虛函數

2011-07-08 10:25:55

JavaScript

2009-06-19 11:13:47

Scalacase類模式匹配

2010-03-11 10:34:22

Scala

2015-07-10 15:31:42

ITIoT物聯網

2009-06-19 11:42:09

Scala計算器解析

2009-07-21 17:21:57

Scala定義函數

2015-09-18 15:22:56

DCIMITSM
點贊
收藏

51CTO技術棧公眾號

香蕉成人app免费看片| 亚洲日本中文字幕| 日韩在线视频观看| 黄色三级中文字幕| 亚洲精品成人av久久| 啦啦啦中文在线观看日本| 日本视频中文字幕一区二区三区| 一区在线中文字幕| 日本一欧美一欧美一亚洲视频| 性生活在线视频| 91在线视频| 亚洲综合精品| 精品999久久久| 国产av不卡一区二区| 糖心vlog精品一区二区| 亚洲性视频大全| 亚洲 欧美综合在线网络| 91日本在线视频| 成人无码精品1区2区3区免费看| 日本不卡1234视频| 成人黄色在线网站| 操日韩av在线电影| 色一情一区二区三区| 国产日本在线| 久久精品在线| 亚洲欧美另类人妖| 男人的天堂99| 毛片免费在线观看| 久色成人在线| 亚洲天堂色网站| 日韩精品一区二区三区不卡| 毛片免费在线观看| 国产91精品一区二区| 欧美黄色小视频| 国产chinesehd精品露脸| 18视频在线观看| 国产精品一二一区| 久久久久久久网站| 蜜桃精品成人影片| 写真福利精品福利在线观看| 日本一区二区三区国色天香 | 香蕉网在线播放| 欧美另类老肥妇| 一区二区三区在线观看视频| 国产成人精品一区二区三区福利| 久久久久久久久久久久久久免费看| 99热这里只有精品首页| 亚洲国产欧美在线| 蜜桃av噜噜一区二区三| 中国老头性行为xxxx| 91久久久精品国产| 精品免费99久久| 91精品91久久久中77777老牛| 黄色毛片在线看| 久久99国产精品麻豆| 欧美国产日韩视频| 多男操一女视频| 超碰在线一区| 日韩精品中文字幕一区 | 久草免费在线| 成人精品电影在线观看| 亚洲一区亚洲二区| 91视频免费网址| 久久国产亚洲精品| 精品99一区二区三区| 亚洲成人福利视频| 2020最新国产精品| 欧日韩精品视频| 欧美这里只有精品| 国产蜜臀在线| 国产精品久久毛片a| 高清日韩一区| 粉嫩av一区二区夜夜嗨| 日日嗨av一区二区三区四区| 欧美成人四级hd版| 99久久精品免费视频| 免费一级欧美片在线观看网站| 欧美性xxxxx极品| 黄色一级片网址| 伊人手机在线| 亚洲一区二区三区三| 亚洲最大色综合成人av| 神马午夜精品95 | 亚洲欧美天堂在线| 毛片在线网站| 色系网站成人免费| 日本欧美视频在线观看| 男人资源在线播放| 久久久久久久网| 国产精品免费在线| 国产精品九九九九| 日日夜夜免费精品| 国产综合在线观看视频| 极品国产91在线网站| 欧美日韩影院| 久久久久www| 日本欧美一区二区三区不卡视频| 欧美国产一区二区三区激情无套| 国产视频精品xxxx| 亚洲成a人无码| 国产精品亚洲欧美一级在线| 欧美三级电影在线看| 黑人糟蹋人妻hd中文字幕| 88xx成人永久免费观看| 91精品国产综合久久香蕉麻豆| 手机看片福利日韩| 不卡福利视频| 岛国av一区二区| 2018国产在线| 久久久精品一区二区毛片免费看| 色婷婷av一区二区三区软件| 欧美日韩在线中文| 亚洲精品三区| 69堂精品视频| 特大黑人巨人吊xxxx| 日韩久久久久| 45www国产精品网站| 天海翼一区二区| 亚洲人成免费| 97香蕉超级碰碰久久免费的优势| 国产亚洲精品久久777777| 美女精品一区| 国产精品中出一区二区三区| 日本不卡在线| 日韩欧美在线网址| 国产女主播在线播放| 日韩在线高清| 国产成人午夜视频网址| 中文字幕日本视频| 99免费精品在线| 欧美精品在线一区| 国产午夜在线观看| 亚洲午夜在线观看视频在线| 91丨九色丨蝌蚪| 精品成人影院| 日韩亚洲欧美成人| 一区视频免费观看| 在线成人国产| 青青在线视频一区二区三区| 精人妻无码一区二区三区| 日本特黄久久久高潮| 精品一卡二卡三卡四卡日本乱码 | 国产曰批免费观看久久久| 国产欧美在线看| 国内三级在线观看| 欧美日韩国产色视频| 精品伦一区二区三区| 欧美在线91| 97超级碰在线看视频免费在线看| 在线观看日韩中文字幕| 奇米影视7777精品一区二区| 鲁丝片一区二区三区| 国产污视频在线播放| 欧美亚洲愉拍一区二区| 波多野结衣在线免费观看| 日本一区二区在线看| 国产精品99蜜臀久久不卡二区| 色综合888| 中文字幕一区二区视频| 女人被男人躁得好爽免费视频| 99国内精品久久久久| 日韩中文字幕网址| 97人妻精品一区二区三区软件 | 欧美日韩电影一区二区三区| 欧美三级网站| 亚洲精品一区二区三区婷婷月| 欧美一级特黄视频| 91热门视频在线观看| 亚洲精品日韩在线观看| 欧美大片黄色| 日韩欧美电影一区| 国产精品18p| 麻豆精品国产传媒mv男同| 国产精品福利视频| 超碰97免费在线| 亚洲激情在线观看视频免费| 亚洲 欧美 变态 另类 综合| 亚洲免费影院| 日韩免费av电影| 91九色国产在线播放| 欧美日韩一区二区欧美激情| 影音先锋男人看片资源| 在线一区视频| 97人人模人人爽视频一区二区| 毛片免费在线播放| 欧美亚洲动漫另类| 国精品无码一区二区三区| 成人午夜免费av| 精品国产一区二区三区在线| 秋霞国产精品| 亚洲精品日韩欧美| aaa在线视频| 亚洲欧美一区二区在线观看| 中文字幕 欧美 日韩| 色呦哟—国产精品| 999日本视频| 日本中文字幕电影在线观看| 欧美色综合久久| 久草综合在线视频| 91视频一区二区三区| 亚洲一区在线不卡| 精品国产一区二区三区av片| 亚洲a成v人在线观看| 色戒汤唯在线观看| 久久精品视频99| 天堂v视频永久在线播放| 亚洲国产日韩a在线播放| 制服 丝袜 综合 日韩 欧美| 国产一区二区91| 国产精品无码专区av在线播放| 天天做天天爱综合| 国产在线视频欧美一区二区三区| 免费看电影在线| 国产一区二区日韩| 朝桐光av在线一区二区三区| 亚洲精品国产无天堂网2021| 亚洲最大成人网站| 天堂蜜桃91精品| 一本—道久久a久久精品蜜桃| 狼人天天伊人久久| 77777少妇光屁股久久一区| 免费黄网站在线| 亚洲精品在线看| 亚洲av无码乱码在线观看性色| 一区二区三区四区不卡在线| 欧洲美熟女乱又伦| 精品一区二区免费看| 亚洲精品在线视频观看| 久久夜色电影| 成人欧美一区二区三区黑人免费| 国产成+人+综合+亚洲欧美| 日韩在线中文字幕| 巨骚激情综合| 亚洲精品白浆高清久久久久久| 国产精品一区二区av白丝下载 | 中文字幕人妻一区二区三区视频| 婷婷久久综合九色综合绿巨人| 亚洲国产综合视频| 久久综合亚州| 大j8黑人w巨大888a片| 精品国产网站| 欧美二区在线| 日韩超碰人人爽人人做人人添| 欧美制服第一页| 国产精品一区hongkong| 免费91在线视频| 美女写真理伦片在线看| 中文综合在线观看| 性中国xxx极品hd| 欧美二区三区91| 日本一级黄色大片| 欧美经典一区二区| 亚洲国产天堂av| 久久久亚洲国产美女国产盗摄 | 色天下一区二区三区| 国产精品jizz视频| 99久久婷婷国产综合精品青牛牛| 福利视频久久| 国产厕拍一区| 国产精品极品美女在线观看免费 | 欧美极品少妇全裸体| 日本色护士高潮视频在线观看| 欧美大尺度激情区在线播放| 羞羞的视频在线看| 欧美国产日产韩国视频| 久草在线中文最新视频| 57pao国产精品一区| 最新欧美色图| 免费91在线视频| 日本在线视频www鲁啊鲁| 欧美黄色片免费观看| 鲁鲁在线中文| 国产aⅴ夜夜欢一区二区三区 | 91久久香蕉国产日韩欧美9色| 日韩人妻精品中文字幕| 亚洲欧美国产毛片在线| 中文字幕成人动漫| 亚洲国产精品v| 自拍视频一区二区| 久久久夜色精品亚洲| 欧美成人短视频| 亚洲精品久久7777| 亚洲视频免费播放| 91久久精品网| 国产又粗又长视频| 精品国产一区二区三区久久影院| 午夜在线观看视频18| 欧美大胆人体bbbb| 天天干天天色天天| 国产一区二区黑人欧美xxxx| 免费成人黄色| 欧美剧在线观看| 色的视频在线免费看| 亚洲美女www午夜| 永久免费av片在线观看全网站| 欧美成人三级视频网站| 午夜不卡影院| 91久久国产精品| 老牛国内精品亚洲成av人片| 亚欧洲精品在线视频免费观看| 亚洲欧美校园春色| 中文字幕一区二区三区乱码| 欧美日韩精品在线一区| 在线观看18视频网站| 日本欧美肥老太交大片| 色阁综合av| 韩日成人在线| 成人午夜免费在线视频| 翔田千里一区二区| 91大神免费观看| 国产色产综合产在线视频| 亚洲午夜久久久久久久久红桃| 中文字幕中文字幕在线一区| 色婷婷在线观看视频| 欧美精选一区二区| 日韩精品视频无播放器在线看| 久久综合国产精品台湾中文娱乐网| 成人免费高清观看| 成人网中文字幕| 日韩有吗在线观看| 国产aⅴ精品一区二区三区黄| 精品国产一区二区三区噜噜噜| 国产精品久久久久久久久电影网| 蜜臀精品一区二区三区在线观看 | 亚洲精品成人久久电影| www视频在线看| 欧美高清在线视频观看不卡| 欧美美女被草| 日本午夜精品一区二区| 色777狠狠狠综合伊人| 亚洲自偷自拍熟女另类| 国产不卡一区视频| 情侣偷拍对白清晰饥渴难耐| 色美美综合视频| 亚洲人成色777777精品音频| 欧美激情在线观看视频| 亚洲日本中文| 亚洲国产精品一区二区第一页| 久久国产精品毛片| 制服丝袜第一页在线观看| 久久亚洲精精品中文字幕早川悠里| 国产色视频一区二区三区qq号| 亚洲综合色自拍一区| 国产精品美女久久久久av爽| 日韩美一区二区三区| 精品176二区| 成人激情视频免费在线| 日韩夫妻性生活xx| 午夜dv内射一区二区| 国内精品在线播放| 日本在线观看网址| 欧美三级在线看| 91社区在线| 国产精品第1页| 欧美丝袜一区| 欧美三级午夜理伦三级富婆| 国产精品1区2区3区在线观看| 好吊一区二区三区视频| 亚洲成人精品影院| 搡老岳熟女国产熟妇| 午夜欧美不卡精品aaaaa| 国产伦乱精品| 欧美成人一区二区在线观看| 91丨九色丨尤物| 亚洲av无码精品一区二区| 亚洲视频在线播放| 日本一区免费网站| 亚洲一区二区三区涩| 久久se这里有精品| 欧美爱爱小视频| 在线免费av一区| 9191在线观看| 亚洲精品欧美日韩| 欧美精品国产一区二区| 国产精品久久久久久亚洲av| 国产精品久久久久久久浪潮网站| 在线观看免费高清视频| 日韩精品极品视频| av免费在线观看网站| 成人免费91在线看| 国产一区二区三区久久| xxxx视频在线观看| 精品久久久久久亚洲国产300| 男女网站在线观看| 国产欧美一区二区三区四区| 欧美jjzz| 女同毛片一区二区三区| 欧美日韩一区二区三区在线| 1769免费视频在线观看| 国产亚洲一区二区三区在线播放| 久久国产主播| av激情在线观看| 日韩精品免费综合视频在线播放| 精品3atv在线视频| 久久国产精品免费一区| 欧美日韩mv| 日韩av在线看免费观看| 制服视频三区第一页精品| av中文字幕在线观看第一页| 视频一区视频二区视频三区视频四区国产 |