日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

用Java和Python模仿Kotlin构建器

發布時間:2023/12/3 python 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 用Java和Python模仿Kotlin构建器 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

介紹

Kotlin可能現在是我最喜歡的語言,并且它可能提供的最酷的功能之一是基于幾個功能構建的類型安全的生成器(稍后解釋)。 我發現自己真的很想在其他兩種主要語言(Java和Python)中使用此功能。 本文解釋了我認為與使用這些語言的類型安全的構建器最接近的東西。

Kotlin

首先,我需要說明Kotlin進行類型安全的構建器的能力。 要快速了解這些構建器的含義,您應該查看有關它們的頁面 。 在本文中,我們將實現其html構建器的一小部分。

Kotlin創建類型安全的構建器的能力歸功于許多小功能。 第一個是lambda語法; {param, list -> block.of.code()} 。 如果lambda的參數為零,則可以忽略參數列表和箭頭。 當它只有一個參數時,也是如此,因為該參數被隱式稱為it 。 例如, {doSomethingWith(it)}是合法的lambda,假設doSomethingWith()接受的對象與傳遞給lambda的對象的類型相同。

下一個功能是如何將lambda傳遞給函數。 如果最后一個參數是lambda,則可以在函數調用的括號后傳遞該參數。 例如, myFunc(arg1){lambdaArg()} 。 如果lambda是唯一的參數,則可以完全忽略括號: aFunc{lambdaArg()} 。 這使您可以定義看起來像語言功能的功能。 如果不是因為保留了這些關鍵字,就可以從技術上定義自己的if-else塊或任何循環。

接下來是擴展方法,您可以定義像它們一樣工作的lambda。 擴展方法是為接口類之外的類或接口定義的新方法。 例如,您可以為String類創建新的方法。 實際上,它們只是靜態方法,它們采用其所針對類型的隱式第一個參數。 在Kotlin代碼中,第一個參數分配給this標識符, this標識符隱式使用,就像在實際方法中一樣。

您也可以定義像擴展方法一樣工作的lambda( SomeClass.() -> Unit而不是(SomeClass) -> Unit ),以便在lambda內部,您可以調用對象而無需顯式引用它。

所有這些功能,再加上非常好的類型推斷,共同構成了一種功能,可以從使用擴展lambda的函數中創建類型安全的構建器。 因此,我們可以這樣寫:

html {head {title("A Title")}body {p = "paragraph"p = "'nother one"p = "last paragraph"} }

要返回Html包含對象Head和Body ,將Head包含Title與文字,“A標題”。 Body包含3個Paragraphs 。

您可能會注意到title和[p]的定義方式不同。 它可能會是聰明有title使用=語法代替p ,但p展示了這些建設者如何素材可以是優于title 。 我用Python做過類似的事情,因為它也支持屬性。

讓我們看一下允許創建這些對象的Kotlin代碼

fun html(htmlBuilder: Html.() -> Unit): Html {val html = Html()html.htmlBuilder()return html }class Html {private var head: Head? = nullprivate var body: Body? = nullfun head(headBuilder: Head.() -> Unit) {head = Head()head?.headBuilder()}fun body(bodyBuilder: Body.() -> Unit) {body = Body()body?.bodyBuilder()} }

我們從Html類和用于啟動構建器的html()函數開始。 html函數不是必需的,因為該代碼可以用作Html構造函數,但是它使我們能夠使構造函數保持簡單,并且所有函數都小寫而不違反命名約定。

您會注意到,實際上一切都還很短。 只有html函數是3行,這僅僅是因為它必須在最后返回結果。 如果我們在Html上使用構造函數,那么它將只有htmlBuilder() 。

這里的Head及Title 。

class Head {private var title: Title? = nullfun title(text: String) {title = Title(text)} }class Title (private val text: String) { }

進行得還不錯。 Title不需要構建器,因為它僅包含文本。 如果不是因為需要一些更復雜的構建機制,我實際上會讓Head只握住String本身,而不是創建Title類和對象。

class Body {private val paragraphs: ArrayList<Paragraph> = ArrayList()var p: Stringprivate get() = null!!set(value) {paragraphs.add(Paragraph(value))} }class Paragraph (private val text: String) { }

這是真正有趣的事情。 與使用Title方法不同,我們沒有使用p()方法,而是使用p的setter來將Paragraph對象添加到列表中。 在這種情況下,它不是最直觀的。 它只是在這里向您展示如何利用這些構建者來發揮創造力。

還要記住,這些類只是構建器類,因此允許它們是有狀態的。 應該有一個build()方法,該方法遞歸地調用所有封閉對象的build()方法,以創建一個不錯的,不變的對象。

Java

在Java中,您幾乎可以創建完全相同的類,除了生成器看起來不那么干凈之外,因為它沒有上面的所有可愛功能。 因此,首先開始,這是構建器代碼的最終外觀。

html(html -> {html.head(head ->head.title("A Title"));ht.body(body -> {body.p("paragraph");body.p("'nother one");body.p("last paragraph");}); });

這是接近的建設者語法,你可以在Java中獲得。 請注意, title()和p()的調用方式沒有什么區別,因為Java不提供任何類似于屬性的構造。 另外,請注意,您需要為所有內容起一個名字。 使用隱式this ,您必須編寫類似于hd.title(...)而不僅僅是title(...) ,這甚至沒有提到我們必須為lambda定義參數列表這一事實。

您還可以做其他幾件事,但更糟糕的是,第一件事就是使用常規代碼:

Html html = new Html();Head head = html.head();head.title("A Title");Body body = html.body();body.p("paragraph");body.p("'nother one");body.p("last paragraph");

這并不可怕 ,但是由于缺少完整類型推斷(我必須指定head和body屬于其各自的類型),它最終變得相對冗長(由于沒有括號,所以多余的制表符純粹是為了外觀)用過的。 我想到的另一種方法將在Python版本之后顯示,因為它試圖復制該版本。

因此,讓我們看一下代碼:

public class Html {public static Html html(Consumer<Html> htmlBuilder){Html html = new Html();htmlBuilder.accept(html);return html;}private Head head = null;private Body body = null;public void head(Consumer<Head> headBuilder) {head = new Head();headBuilder.accept(head);}public void body(Consumer<Body> bodyBuilder) {body = new Body();bodyBuilder.accept(body);} }

這與直接移植到Java一樣直接。 html()函數已作為靜態方法移入Html類,因為它必須放在 Java中。 我們使用了Consumer<Html> ,因為這是Java與我們想要的lambda最為接近的東西。

這里是Head和Title :

public class Head { private Title title = null;public void title(String text) {title = new Title(text);} }public class Title {private final String text;public Title(String text) {this.text = text;} }

這里沒有太多注意事項。 這可能與您的期望有關。 現在以“ Body Paragraph結束。

public class Body {private final List paragraphs = new ArrayList<>();public void p(String text) {paragraphs.add(new Paragraph(text));} }public class Paragraph {private final String text;public Paragraph(String text) {this.text = text;} }

幾乎感覺像不值得編寫這些類,不是嗎,它們是如此簡單。 請記住,這是準構建器部分。 同樣,此代碼實際上并不包含用于構建實際的,不變的DOM樹的功能。

這就是構建Java版本所需要的。 除了一些語法上的冗長之外,用Java創建比使用Kotlin幾乎容易得多,因為沒有任何其他功能可以考慮和使用:P

Python

試圖找出一種在Python中執行類似操作的方法,這使我很幸運地看到了一個視頻,該視頻展示了使用上下文管理器( with語句)的新穎(但不直觀)的方法。 Python中的問題在于,lambda只允許具有單個表達式或語句。 上下文管理器通過有效地允許您在可以在上下文管理器內使用的條目上返回一個對象(或不返回任何對象),從而允許(非常有限的)方式繞過單行lambda,就像在lambda內一樣。

因此,例如,構建器在Python中如下所示:

myhtml = Html() with myhtml as html:with html.head() as head:head.title("A Title")with html.body() as body:body.p = "paragraph"body.p = "'nother one"body.p = "last paragraph"

這實際上看起來像是浪費,因為這幾乎可以很容易地寫成以下內容:

html = Html() head = html.head() head.title("A Title") body = html.body() body.p = "paragraph" body.p = "'nother one" body.p = "last paragraph"

with塊的最大好處是縮進,因為Python由于在花括號上使用縮進,因此具有縮進限制。 為此,上下文管理器可能值得。 但是,在向您展示了用Python制作這些代碼所需的基本代碼之后,我還將在書中談到另一個好處:

class Html:def __enter__(self):return selfdef __exit__(self, exc_type, exc_val, exc_tb):return Falsedef head(self):self._head = Head()return self._headdef body(self):self._body = Body()return self._body

在這里,你可以看到Html類具有所需的__enter__()和__exit__()方法是一個上下文管理器。 他們幾乎什么也不做; __enter__()僅返回self ,而__exit__()僅表示它__exit__()任何可能傳入的異常__exit__() head()和body()方法幾乎可以滿足您現在的期望, Head和Body也是上下文管理器類型的假設。

class Head:def __enter__(self):return selfdef __exit__(self, exc_type, exc_val, exc_tb):return Falsedef title(self, text):self._title = Title(text)class Title:def __init__(self, text):self.text = textclass Body:p = property()def __enter__(self):return selfdef __exit__(self, exc_type, exc_val, exc_tb):return False@p.setterdef p(self, text):if not hasattr(self, 'paragraphs'):self.paragraphs = []self.paragraphs.append(Paragraph(text))class Paragraph:def __init__(self, text):self.text = text

唯一值得關注的新事物是在Body中為其p標簽使用了property 。 幸運的是,我們并不需要對干將property ,我們需要有返回小號None ,就像在Kotlin。

好的,現在我們來看一個有趣的,不太明顯的原因,在這種情況下使用上下文管理器會有所幫助。 在Java和Kotlin中,我們最終需要對build()方法進行一次額外的調用(或者讓html()函數為我們完成),并讓它最后一次全部進行遞歸遍歷照顧它。 使用上下文管理器, __enter__() __exit__() __enter__()和__exit__()方法可以在進入時傳遞對象的生成器版本,然后在退出時進行構建。 這意味著構建器的每個中間階段在退出時已經包含完整構建的版本。

實際上,將頭纏繞起來可能有點困難。 這是一個使用Html , HtmlBuilder和Head進行部分實現的示例:

class Html:def __enter__(self):self._builder = HtmlBuilder()return self._builderdef __exit__(self, exc_type, exc_val, exc_tb):self.head = self._builder._headself.body = self._builder._bodydel self._builderreturn Falseclass HtmlBuilder:def head(self):self._head = Head()return self._headdef body(self):...class Head:def __enter__(self):self._builder = HeadBuilder()return self._builderdef __exit__(self, exc_type, exc_val, exc_tb):self.title = self._builder._titledel self._builderreturn False

在這里, Html對象的__enter__()方法創建并保存一個生成器,然后將其返回。 在__exit__() ,它從存儲在構建器中的值構建自身,并從自身中刪除構建器。 一經考慮,至少對于我來說,可能會認為存儲在構建器上的對象不是完成的對象,而是完成的對象。 使用HtmlBuilder的head()方法和Head的實現可以看到,builder對象上的方法返回具有其自己的__exit__() __enter__()和__exit__()方法的適當類,這些類也將保證其正確構建。 使用此設置,調用代碼實際上仍然與第一次相同。

最后一件事:既然我們知道可以使用上下文管理器來執行此操作,那么您可能會認為Java的try資源管理器實際上可以正常工作。 而且你會是對的。 實際上,它的最終語法(除了隨機try關鍵字之外)也比lambda版本更干凈。 調用時,資源管理器的版本如下所示:

Html html = Html(); try(html) {try(Head head = html.head()) {head.title("A Title");}try(Body body = html.body()) {body.p("paragraph");body.p("'nother one");body.p("last paragraph");} }

在這一點上,我將留給您嘗試并弄清楚如何實現它。 提示:我認為它不能像Python構建的第二個版本那樣工作,它會隨其構建。 我認為此Java版本代碼中的所有內容都需要構建器,直到最后,您在html上調用build()方法以創建真實版本。

奧托羅

天哪,這東西最終有點長,不是嗎? 我希望您能從此練習中獲得一些樂趣,因為我不確定它的實際用途(除了了解您可以使用上下文管理器模擬0或1參數lambda外,還可以。

可悲的是,我從來沒有像在Kotlin網站的示例中那樣談論添加其他參數,例如在函數調用中分配類,id等。 Kotlin還具有其他功能,可以使它真正干凈和容易,但是本文顯然沒有足夠的空間。 下周我會解決。

謝謝閱讀!

注意:截至昨天,所有編輯已完成。 從這里開始,我“只是”需要設計一個我有想法的封面; 獲取所有印刷版和電子書版的格式; 編寫附錄(大部分只是本書中的代碼片段的集合,充實了更多內容); 并完成GitHub存儲庫的編寫,該庫將具有所有超級有用的類和函數,可更快,更輕松且更少的問題來構建自己的描述符。 我希望所有這些工作都能在夏季結束之前完成,但希望能早日完成。 我的生活將變得更加忙碌,所以我不知道我能花多少時間來完成所有這些工作。

翻譯自: https://www.javacodegeeks.com/2016/01/mimicking-kotlin-builders-java-python.html

總結

以上是生活随笔為你收集整理的用Java和Python模仿Kotlin构建器的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 日韩图片区 | 黄色三级视频在线观看 | 亚色在线视频 | 18禁肉肉无遮挡无码网站 | 国产成a人亚洲精v品在线观看 | 午夜伦理剧场 | 欧美精品一区二 | 神马三级我不卡 | 伦理黄色片 | 日本黄色网址大全 | av福利在线 | 日本网站免费 | 国产乱人乱偷精品视频a人人澡 | 国产在线视频在线观看 | 98自拍视频 | 国产亚洲片 | 91激情在线观看 | 91精品视频免费看 | 国产精品-色哟哟 | 欧美性猛交xxxx黑人交 | 亚洲激情在线观看 | 国产精品一区在线免费观看 | 亚洲精品乱码久久久久久蜜桃麻豆 | 色交视频 | 30一40一50女人毛片 | 九九久久国产 | 久久六 | 亚洲网在线观看 | av中文字幕第一页 | 高清日韩一区 | 亚洲精品三 | 暖暖免费观看日本版 | 国产精品欧美精品 | 性生活av| 黄色成人影视 | 天天干天天操av | 艳情五月 | 少妇av在线播放 | 国产福利午夜 | 亚洲女人被黑人巨大进入 | 国产吃瓜黑料一区二区 | 亚洲色鬼 | 中国美女一级看片 | 国产在线国偷精品免费看 | 欧美激情免费在线 | 亚洲天堂777| 亚洲一区二区图片 | 免费av不卡在线观看 | 黄色岛国片 | 一个色在线视频 | 狠狠干中文字幕 | 亚洲大片免费看 | 精品人妻少妇一区二区三区 | 色综合九九 | 国产高清精品一区二区三区 | 男插女视频在线观看 | 亚洲国产看片 | 激情777| 免费爱爱网站 | 看黄色大片| 欧美色图亚洲天堂 | 中文字幕久热 | 影音先锋成人在线 | 大尺度做爰床戏呻吟舒畅 | 青草久久久久 | 少妇高潮av久久久久久 | 国产日韩欧美一区 | 蜜臀av色欲a片无码精品一区 | 18无码粉嫩小泬无套在线观看 | 黑人玩弄人妻一区二区三区四 | 精品人妻无码一区二区三区换脸 | 99久 | 日韩免费视频观看 | 欧美人与性禽动交精品 | 日本不卡视频在线播放 | 久久人人爽人人爽人人av | 插插插综合 | www欧美日韩| 国产视频一区二区三区在线播放 | 欧美一级淫片免费视频黄 | 久艹在线视频 | 在线资源站 | av免费一区 | 国产亚洲女人久久久久毛片 | 一本大道一区二区 | 三级黄色在线 | 国产一卡二卡三卡 | 777久久久精品一区二区三区 | 欧美日韩在线免费播放 | xxxxwwww在线观看| 精品在线视频免费 | 国产在线精品视频 | 亚洲国产精品无码久久 | 天天干夜夜玩 | 老熟妇仑乱一区二区视频 | 亚洲啪av永久无码精品放毛片 | 成人做爰69片免费看 | 免费黄在线 | 亚洲黄在线 |