说,我有一个ClassA
和ClassB
,每个都需要在各自的构造函数中有自己的参数:
ClassA <- function(A_arg1, A_arg2) {
# some class-SPECIFIC construction magic happens, say
out <- list(A_arg1, A_arg2)
# some GENERAL construction magic happens
class(out) <- "ClassA"
return(out)
}
ClassB <- function(B_arg1, B_arg2) {
# some class-SPECIFIC construction magic happens, say
out <- B_arg1 + B_arg2
# some GENERAL construction magic happens
class(out) <- "ClassB"
return(out)
}
我的实际用例有点复杂;我正在尝试使用构造函数和check.ClassName()
方法将类型验证变为S3
。
显然,我希望避免上述构造函数的通用部分中的重复,因此可以像这样使用的函数工厂会很好:
ClassA <- produce_class_constructor(classname = "ClassA", fun = function(A_arg1, A_arg2) {return(list(A_arg1, A_arg2))})
理想情况下,这应该产生与上述手动构造的ClassA
函数完全相同的函数,其中一般部分被考虑在内。
(在我的实际用例中的一般部分相当长一点)。
警告:工厂生成的ClassA()
构造函数保留参数名称(此处为A_arg1
,A_arg2
)至关重要,以便文档和自动完成可以指导用户进行构建。
我想使用最佳功能编程(FP)实践来解决这个问题。
我previously asked关于通过一个简单的闭包来做这件事,但我知道是否想通过function operators这样做可能不是一个更好的方法,我只是换行(或compose
)每个类的特定部分周围的一般运算符,以产生每个类的构造函数。
在伪代码中,我想设计这样的东西:
produce_class_constructor <- function(classname, fun) {
class_constructor_func <- validate_class(append_class(classname, fun()))
}
其中,append_class()
使自定义fun
也附加了某个类,validate_class()
反过来也会对其结果进行自定义fun
运行检查。
然后我可以使用这个构造函数因子来优雅地创建上面的ClassA()
:
ClassA <- produce_class_constructor(classname = "ClassA", fun = function(A_arg1, A_arg2) {return(list(A_arg1, A_arg2))})
这是我的简单(失败)尝试。
# simple helper to append classes
append_class <- function(obj, classname) {
class(obj) <- append(class(obj), classname)
return(obj)
}
produce_class_constructor <- function(classname, fun) {
force(fun) # not sure what this does, but seems to be necessary as per http://adv-r.had.co.nz/Function-operators.html
# all the GENERAL construction magic from above now happens here
class_constructor_fun <- function(...) {
append_class(classname, fun(...))
}
formals(class_constructor_fun) <- formals(fun) # this is necessary to carry over argument names
return(class_constructor_fun)
}
ClassB <- produce_class_constructor(classname = "ClassB", fun = function(B_arg1, B_arg2) {
# this is the class-SPECIFIC construction magic from above
out <- B_arg1 + B_arg2
return(out)
})
ClassB(B_arg1 = 1, B_arg2 = 2) # this fails
好消息是生成的ClassB()
已命名参数。
坏消息是他们没有被传递,整个事情都失败了:
Error in append(class(obj), classname) :
'...' used in an incorrect context
S3
? (其他OO不是一种选择,可以吓跑我的裤子。)