Предварительно: я знаючто R — это функциональныйязык, поэтому, пожалуйста, не кусайтесь ; -)
У меня был отличныйопыт использования ООП-подхода во многих моих программах. Теперь мне интересно, есть ли способ провести различие между общедоступными и частными методами при использовании эталонных классов S4в R?
setRefClass("B",
field=list(
b.1="numeric",
b.2="logical"
),
methods=list(
thisIsPublic=function(...) {
thisIsPublic_ref(.self=.self, ...)
},
thisIsPrivate=function(...) {
thisIsPrivate_ref(.self=.self, ...)
}
)
)
setRefClass("A",
field=list(
a.1="B"
)
)
ПРИМЕЧАНИЕ
Обычно я не помещаю определение фактическогометода в определение класса, а разделяю его на метод S4 (т.е. thisIsPublic_ref
] ) по следующим причинам:
x
экземпляром определенного класса, вы можете вызвать foo_ref(.self=x)
вместо x$foo()
.компилятора::cmpfun()
, что, я думаю, невозможно, если у вас есть «простые» методы ссылочного класса.Безусловно, не имеет смысла усложнять этот конкретный пример, но тем не менее я решил проиллюстрировать этот подход.
setGeneric(
name="thisIsPublic_ref",
signature=c(".self"),
def=function(
.self,
...
) {
standardGeneric("thisIsPublic_ref")
}
)
setGeneric(
name="thisIsPrivate_ref",
signature=c(".self"),
def=function(
.self,
...
) {
standardGeneric("thisIsPrivate_ref")
}
)
require(compiler)
setMethod(
f="thisIsPublic_ref",
signature=signature(.self="B"),
definition=cmpfun(function(
.self,
...
){
.self$b.1 * 1000
})
)
setMethod(
f="thisIsPrivate_ref",
signature=signature(.self="B"),
definition=cmpfun(function(
.self,
...
){
.self$b.2
})
)
x.b <- new("B", b.1=10, b.2=TRUE)
x.a <- new("A", a.1=x.b, a.2="hello world")
Экземпляры класса A
(т.е. xa
) должны иметь возможность использовать класс B
's publicметоды:
> x.a$a.1$thisIsPublic()
[1] 10000
Экземпляры класса A
(то есть xa
) должны notиспользовать класс Б
частныеметоды. Поэтому я бы хотел, чтобы это неработало, т. е. приводило к ошибке:
> x.a$a.1$thisIsPrivate()
[1] TRUE
Любая идея, как это можно указать?
Единственное, что я пока придумал:
Добавляем аргумент sender
в каждый метод, явно указываем его для каждого вызова метода и проверяем, если class(.self) == класс(отправитель)
. Но это кажется немного «явным».