Доступ к классам из определенного пакета
getClass()
new()
принимает объект classRepresentation
, который вы можете получить используя getClass
. Например, new(getClass('className', where='packageName'))
. Однако обратите внимание, что это не будет работать, если вы еще не импортировали пакет, а также определили новый класс с тем же именем. Я демонстрирую эту проблему здесь:
install.packages('lookupTable')
setClass('lookupTable', slots = c(notworking='numeric'))
new(getClass('lookupTable', where='lookupTable'))
#> An object of class "lookupTable"
#> Slot "notworking":
#> numeric(0)
(он напечатал нерабочий слот, что означает, что он создает экземпляр моего пользовательского класса, а не правильной версии пакета)
new(classNameWithAttribute)
В new
есть странная, но задокументированная функция, которая позволяет вам установить атрибут package
для имени класса, который на самом деле работает отлично (т.е. не имеет проблемы, упомянутой выше), если немного подробно:
name = 'className'
attr(name, 'package') = 'packageName'
new(name)
Однако нет причин, по которым вы не могли бы превратить это в функцию многократного использования:
new = function(cls, pkg, ...){
attr(cls, 'package') = pkg
methods::new(cls, ...)
}
new('className', 'packageName')
Хороший дизайн упаковки
Конечно, всего этого можно избежать, если упаковщики классов S4 предусмотрят один из двух механизмов:
Экспорт значения setClass()
setClass()
имеет как побочный эффект (сохранение класса в реестре), так и возвращаемое значение (функция генератора классов). Поэтому, если упаковщик решит сохранить и экспортировать возвращаемое значение в свой NAMESPACE
, мы сможем получить к нему доступ позже:
# In package "myPackage"
myClass = setClass('myClass')
# In package's NAMESPACE
export(myClass)
# In user's script
new(myPackage::myClass)
Например, вы можете проверить это с помощью того же тестового пакета, что и раньше:
install.packages('lookupTable')
new(lookupTable::lookupTable)
Экспорт функции-конструктора
Это стандартная практика в биокондукторе. Они определяют функцию-конструктор с тем же именем, что и сам класс. Затем вы можете получить доступ к функции конструктора, используя ::
, и вызвать ее вместо new
:
install.packages("BiocManager")
BiocManager::install("IRanges")
new("IRanges")
# Equivalent to
IRanges::IRanges()
person
Migwell
schedule
30.03.2021
myFunc
существует в обоих пакетах, тоA::myFunc()
иB::myFunc()
допускают устранение неоднозначности. НоsetClass()
,new()
и т. д. используют строки для имен классов и, похоже, не понимают префиксы пакетов. Нигде не могу найти на это ответ. - person Stuart R. Jefferys   schedule 20.03.2021