是否可以从类外部向类中添加成员变量? (或者模仿这种行为?)
以下是我尝试做的一个例子。我已经使用隐式转换向final int top = 50;
final Duration windowSize = standardMinutes(60);
final Duration windowPeriod = standardMinutes(10);
final SlidingWindows window = SlidingWindows.of(windowSize).every(windowPeriod);
options.setWorkerMachineType("n1-standard-16");
options.setWorkerDiskType("compute.googleapis.com/projects//zones//diskTypes/pd-ssd");
options.setJobName(applicationName);
options.setStreaming(true);
options.setRunner(DataflowPipelineRunner.class);
final Pipeline pipeline = Pipeline.create(options);
// Get events
final String eventTopic =
"projects/" + options.getProject() + "/topics/eventLog";
final PCollection<String> events = pipeline
.apply(PubsubIO.Read.topic(eventTopic));
// Create toplist
final PCollection<List<KV<String, Long>>> topList = events
.apply(Window.into(window))
.apply(Count.perElement()) //as eventIds are repeated
// get top n to get top events
.apply(Top.of(top, orderByValue()).withoutDefaults());
添加了其他函数,因此我向RDD
添加了一个变量。我猜这不起作用,因为变量在ExtendedRDDFunctions
调用转换后丢失了。
有没有办法获得这种功能?这是错误的做法吗?
rdd.setMember(string)
编辑:
我使用以下函数:首先调用implicit def toExtendedRDDFunctions(rdd: RDD[Map[String, String]]): ExtendedRDDFunctions = {
new ExtendedRDDFunctions(rdd)
}
class ExtendedRDDFunctions(rdd: RDD[Map[String, String]]) extends Logging with Serializable {
var member: Option[String] = None
def getMember(): String = {
if (member.isDefined) {
return member.get
} else {
return ""
}
}
def setMember(field: String): Unit = {
member = Some(field)
}
def queryForResult(query: String): String = {
// Uses member here
}
}
,然后调用rdd.setMember("state")
。
答案 0 :(得分:3)
由于每次调用ExtendedRDDFunctions
中定义的方法时都会应用隐式转换,因此每次调用ExtendedRDDFunctions
和setMember
都会创建一个新的queryForResult
实例。这些实例不共享任何成员变量。
您基本上有两种选择:
Map[RDD, String]
的伴随对象中维护ExtendedRDDFunctions
,用于将member
值分配给setMember
中的RDD。当你为一系列错误引入全球状态和公开陷阱时,这是一个邪恶的选择。创建一个包含member
值的包装类,并由setMember
方法返回:
case class RDDWithMember(rdd: RDD[Map[String, String]], member: String) extends RDD[Map[String, String]] {
def queryForResult(query: String): String = {
// Uses member here
}
// methods of the RDD interface, just delegate to rdd
}
implicit class ExtendedRDDFunctions(rdd: RDD[Map[String, String]]) {
def setMember(field: String): RDDWithMember = {
RDDWithMember(rdd, field)
}
}
除了省略的全局状态,此方法也更安全,因为您无法在没有queryForResult
的实例上调用member
。唯一的缺点是您必须委派RDD
的所有成员,并且queryForResult
本身未定义RDD
。
第一个问题可能可以通过一些宏魔术来解决(搜索“委托”或“代理”和“宏”)。
可以通过在ExtendedRDDFunctions
中定义额外的扩展方法来解决后一个问题,该方法会检查RDD
是否为RDDWithMember
:
implicit class ExtendedRDDFunctions(rdd: RDD[Map[String, String]]) {
def setMember(field: String): RDDWithMember = // ...
def queryForResult(query: String): Option[String] = rdd match {
case wm: RDDWithMember => Some(wm.queryForResult(query))
case _ => None
}
}
答案 1 :(得分:0)
import ExtendedRDDFunctions._
将导入Companion对象中的所有属性和函数,以便在类的主体中使用。
根据您的用法寻找delagate模式。