Java和Python中类似Kotlin的生成器,续:附加参数
介绍
在今天的文章中,我们将继续上周的文章,内容涉及用Java和Python制作类似于Kotlin的构建器,扩展构建器API以采用一些可选参数来提高灵活性。 我们继续我们HTML示例,尝试添加标记属性,例如类,id和样式。
Kotlin和Python
Kotlin设置这些参数的用法的方式与我在Python中的使用方式完全相同:默认参数和命名参数。 使用Kotlin看起来像这样:
html {body {p(klass="myClass", id="theParagraph") {+ "the paragraph text"}}
}
请注意,使用“杯子”而不是“类”。 关键字和标识符的经典冲突。 您可以根据需要使用“ cls”,“ clazz”或其他任何东西。 我建议不要使用类对象语言中通常使用的任何东西,因为这是完全不同的类。
与上周的p
标签相比,这是一个很大的升级(只是p = "text"
),将其从属性更改为成熟的方法。 但是大多数其他示例不需要太多工作。 这是更新的Kotlin代码:
class Body {...fun p(class: String="", id: String="", style: Style=Style.blank, paragraphBuilder: Paragraph.() -> Unit) {val p = Paragraph(class, id, style)paragraphs.add(p)p.paragraphBuilder()}...
}class Paragraph(val class: String, val id: String, val style: Style) {var text: String = ""operator fun plus(other: String) {text += other}
}
更新后的Python代码(仍使用第一个版本)如下所示:
class Body:def __init__(self):self.paragraphs = ...def p(self, klass='', id='', style=None):par = Paragraph(klass, id, style)self.paragraphs.append(par)return parclass Paragraph:def __init__(self, klass, id, style):self.klass = klassself.id = idself.style = styleself.text = ''def __enter__(self):return selfdef __exit__(self, exc_type, exc_val, exc_tb):return Falsedef __iadd__(self, text):self.text += text
__iadd__()
是就地加法运算符,允许我们说p += 'text'
。 在Kotlin中,我们使用+
而不是+=
因为我们不必引用段落对象,因此以+=
开头似乎是错误的,而我们需要在Python代码中引用p
,因此+=
看起来更自然,这样,我们就可以将调用代码更改为以下形式:
html = Html()
with html as html:with html.body() as body:with body.p(class='myClass', id='theParagraph') as p:p += 'the paragraph text'
Kotlin和Python都采用Style
对象,而不是像其他字符串一样仅接受另一个字符串。 实际上,我建议也对class和id做同样的事情,因为从那时起,我们将class和id对象及其CSS设置传递给CSS生成器。 我只是为了举例而没有在这里做。 我不让Style
保留字符串,因为最好使用某种CSS样式生成器来提供更好的清晰度和正确性。
Java
Kotlin和Python都使过渡非常简单。 不幸的是,Java没有设置必需的功能来进行如此简单的更改。 您必须依靠古老的流利的API技巧来使您顺利通过。
重载嘉豪!
首先想到的是尽可能多地进行带有大量重载的转换。 您可以为class和id字段创建快速,方便的字符串包装器,因为它们都只是字符串,因此很难区分两者:
class Class {public final String text;public Class(String text) {this.text = text;}
}class ID {public final String text;public ID(String text) {this.text = text;}
}
这使得所有重载看起来像这样:
class Body {...public void p(Consumer<Paragraph> paragraphBuilder) {...}public void p(Class klass, Consumer...) {...}public void p(ID id, Consumer...) {...}public void p(Style style, Consumer...) {...}public void p(Class klass, ID id, Consumer...) {...}// and so on... 3 more times...
}
这变得非常乏味,以至于我什至没有写完每一行,更不用说开始所有行了。 而且这仅考虑了类,id和样式。 还有更多。 走这条路是不好的。 因此,我什至不会显示结果代码的样子。 另外,对于其余的想法,我不会费心地展示API的实现,希望它是不言而喻的。 如果您真的对如何实现一种API感到好奇,请告诉我。
内部设定
设置这些属性的另一种方法是在构建器中进行设置。 提供用于设置这些值的“ Paragraph
方法。 在body标签内看起来像这样:
html.body(body -> {body.p(p -> { p.klass = "myClass"; p.id = "theParagraph";p.addText("the paragraph text");});
});
这并不可怕(尤其是在第一行上有那些设置程序行;将它们放在后续行上会混淆其目的),并且这可能是最简单的,但是错误代码的可能性却很高:
html.body(body -> {body.p(p -> {p.klass = "myClass";p.addText("the paragraph text");p.id = "theParagraph";});
});
让我们看看其他选项。
属性对象
仅使用p()
两个重载(一个仅接受构建器函数,而一个重载并与Attributes
对象一起),我们可以制作一个非常干净的API,看起来像这样:
html.body(body -> {body.p(Attributes.klass("myClass").id("theParagraph"), p -> {p.addText("the paragraph text");});
});
就个人而言,这是我的最爱。 它需要更多的类和更多的实际复杂性,但是我觉得它是最可扩展的。 最大的不便是不同HTML标签具有不同的属性集。 可能应该有一个公共的“ Attributes
构建器类,再加上一个特定于标记的类,从而使重载次数最多达到4(没有属性,只有基本的属性,只有特定于标记的属性,以及这两种类型)。 四个重载是可以容忍的,但可能不应该。 如果看起来太多,最好还是坚持最后一种策略。
为了完整起见,我还有一个,它实际上可能对其他不模仿HTML或XML的API更好地工作。
通话后大楼
最后一个想法是让Body.p()
返回Paragraph
(最好是构建器的第二阶段,因为这些方法可以在构建器lambda中使用,否则可以)调用这些方法,如下所示:
html.body(body -> {body.p(p -> {p.addText("the paragraph text");}).klass("myClass").id("theParagraph");
});
这实际上将Attributes
类移到末尾,作为“ Paragraph
构建器的第二阶段。
奥托罗
那是我能给你的最好的。 如果您有兴趣使用Java之类的语言来构建流畅的API,则应查阅jOOQ的文章,了解它们的用法 。 这是一种完全不考虑lambda的不同方式,这很好。 无论如何,下周我将发表一系列简短的书评文章时,我将与你们交谈。
翻译自: https://www.javacodegeeks.com/2016/01/kotlin-like-builders-java-python-continued-additional-parameters.html
Java和Python中类似Kotlin的生成器,续:附加参数相关推荐
- python kotlin_Java和Python中类似Kotlin的生成器,续:附加参数
python kotlin 介绍 在今天的文章中,我们将继续上周的文章,内容涉及使用Java和Python创建类似Kotlin的构建器,并扩展了构建器API以采用一些可选参数以提高灵活性. 我们继续我 ...
- python中算法(sklearn)的最优超参数寻优:skopt贝叶斯搜索
python中算法(sklearn)的最优超参数寻优:skopt贝叶斯搜索 Jeff Dean在ICML 2019上进行了有关AutoML的演讲,并将自动化分为4个级别 手动构造预测变量,不引入学习的 ...
- python获取命令行参数_【整理】Python中如何获得并处理命令行参数
运行Python脚本时,时常需要从命令行中传递一些参数到Python程序中,但是如何获得相应的传递进来的参数,以及如何解析这些参数,是很多人,包括最开始的我,所遇到的问题. 下面,就对此总结一下: 先 ...
- 关于C++,Java和Python中的随机数生成法
首先我们来说说C++中的随机数生成: 我们知道在C++用函数rand()获取的是一个0 ~ RAND_MAX之间的一个随机数.其中RAND_MAX的值为32767. 首先我们来分析两个程序: #inc ...
- 【Python】Python中的迭代器和生成器
迭代器和生成器在很多编程语言中都会以不同形式的存在,在实际编程中经常会被用到.下面我们来了解一下什么是迭代. 1 迭代 了解Java的AIAS行者(AI行者是我B站粉丝勋章名称)应该都会知道,在Jav ...
- python中的函数、生成器的工作原理
1.python中函数的工作原理 def foo():bar()def bar():pass python的解释器,也就是python.exe(c编写)会用PyEval_EvalFramEx(c函数) ...
- python中的迭代器,生成器,闭包,装饰器,@property
一.迭代器 迭代器在Python中无处不在.它们在for循环,理解,生成器等中优雅地实现,但却隐藏在眼皮底下. Python中的Iterator只是一个可以迭代的对象.一个将返回数据的对象,一次返回一 ...
- python 生成器 原理_你知道python中的函数、生成器的工作原理吗?
1.python中函数的工作原理 python的解释器,也就是python.exe(c编写)会用PyEval_EvalFramEx(c函数)运行foo()函数 首先会创建一个栈帧(stack Fram ...
- 正则表达式及其在Java和Python中的相关操作
1.PCRE表达式全集1 字符 描述 \ 将下一个字符标记为一个特殊字符.或一个原义字符(有^$()*+?.[\{|共计12个)或一个向后引用或一个八进制转义符 ^ 匹配输入字符串的开始位置 $ 匹配 ...
最新文章
- C语言实现图像中值滤波与均值滤波
- hive sql 报错后继续执行_Hive迁移Presto的技术实践
- 浅析网站建设必要的专用软件
- 用电线来传网络信号的黑科技?AirGig究竟是什么
- 数据结构树的基本操作_[数据结构]树的建立与基本操作 解题报告
- mac m1下golang连接mysql极速入门
- 百度地图隐藏LOGO显示
- 在.NET Core日志记录中使用Trace和TraceSource
- linux epoll用法之二
- Telepresence修改完善心得
- 用struts拦截器实现登录验证功能AuthorizationInterceptor
- python实现mysql数据导入HBase
- php导出excel处理微信昵称emoji表情符号和特殊颜文字符
- 5. Carla中Recorder(记录器)的使用
- 【字符集五】c++标准库<locale>
- CentOS 6.X yum源更新(阿里云默认最新更新为CentOS6.10)
- 小红书去水印源码算法
- v免签对接易支付插件(已测试)
- 一个简单的SpringBoot项目 demo
- 单片机定时器精准定时_如何确保单片机精确定时控制有哪些编程方法详细说明...