Я хотел бы использовать несколько конструкторов в моем классе R S4.
У меня есть объект, который имеет три слота. Чтобы сделать этот объект, иногда я хочу просто дать значения для трех слотов. Но иногда я хотел бы предоставить матрицу, и у меня есть функция, которая может взять матрицу и вернуть, какими должны быть эти три слота.
Сначала кажется, что я мог бы написать функцию в качестве конструктора. Так что я мог бы написать objectFromMatrix(matrix) --> object with three slots
. Проблема в том, что у меня также есть подклассы, которые наследуются от этого основного класса, и я хочу иметь возможность использовать этот конструктор вместе с ними.
Так что я мог бы просто написать функции в качестве дополнительных конструкторов для каждого из подклассов, но это было бы немного утомительно и не супер OO-подобным.
Чтобы сделать мою проблему немного более ощутимой, я постараюсь написать минимальный пример ниже. Я напишу это на Java, но я немного заржавел, поэтому дайте мне знать, если это не имеет смысла.
Желаемая структура в Java:
// An abode is a place where you live and it has a size
class Abode {
int size = 1;
// Main constructor that just assigns args to fields
Abode(int size) {
this.size = size;
}
// Alternative constructor that takes in a different datatype
// and computes args to assign to fields
Abode(string description) {
if(description eq "Large") {
this.size = 5;
}
if(description eq "Small") {
this.size = 1;
}
}
// To keep it simple, a house is just an abode with a name
class House extends Abode {
String name;
House(int size, String name) {
super(size);
this.name = name;
}
House(string size, String name) {
super(size);
this.name = name;
}
}
Эта реализация хорошо работает, потому что я могу вызвать Abode("big")
или House("big", "Casa de me")
, и оба они будут переданы дополнительному конструктору, который я построил в классе Abode
.
Следуя аналогии с домом, это лучшее, что я смог сделать в R:
# An abode is a place you live and it has a size
setClass("Abode",
slots =
list(size = "numeric")
)
# Alternative constructor that takes in a different datatype
# and computes args to assign to fields
abode_constructor_2 <- function(sizeString) {
if (sizeString == "big") {return new("Abode", size = 5)}
if (sizeString == "small") {return new("Abode", size = 1)}
}
# A house is an abode with a name
setClass("House",
slots =
list(name = "string"),
contains = "Abode"
)
# I already defined this constructor but I have to do it again
house_constructor_2 <- function(sizeString, name) {
if (sizeString == "big") {return new("House", size = 5, name = name)}
if (sizeString == "small") {return new("House", size = 1, name = name)}
}
В случае, если это поможет, вот минимальный пример реального контекста, в котором возникает эта проблема. Я определяю дополнительный конструктор для класса Sensor
, sensor_constructor_2
, как функцию. Но затем, когда у меня есть класс, который наследуется от Sensor
, мне придется заново создать этот конструктор.
# A sensor has three parameters
setClass("Sensor",
slots =
list(Rmin = "numeric", Rmax = "numeric", delta = "numeric")
)
# I also like to make sensors from a matrix
sensor_constructor_2 <- function(matrix) {
params <- matrix_to_params(matrix)
return (new("Sensor", Rmin = params[1], Rmax = params[2], delta = params[3]))
}
# A redoxSensor is just a sensor with an extra field
setClass("redoxSensor",
slots =
list(e0 = "numeric"),
contains = "Sensor"
)
# Goal: make this extra constructor unnecessary by making sensor_constructor_2 a property of the sensor class
extraConstructor_redox <- function(matrix, e0) {
params <- matrix_to_params(matrix)
return (new("redoxSensor", Rmin = params[1], Rmax = params[2], delta = params[3]), e0 = e0)
}