Uzupełnienie mój komentarz raczej zapewniając nową odpowiedź na pytanie, oto rozwiązanie, gdzie nadal pasuje argumenty o położeniu (bo określić dodatkowe reprezentację klasy B):
.A <- setClass("A", representation(a="character"))
.B <- setClass("B", representation(b="numeric"),
prototype(a="hello"),
contains="A")
.A()
i .B()
zastąpić wywołań new("A")
i new("B")
. Na pewnym poziomie jest to cukier syntaktyczny, ale może sprawić, budowa obiektu bardziej przejrzysty
## construct an object using B's prototype, like new("B", b=1:3)
> .B(b=1:3)
An object of class "B"
Slot "b":
[1] 1 2 3
Slot "a":
[1] "hello"
## construct an object using A's prototype, like new("B", new("A"), b=1:3)
> .B(.A(), b=1:3)
An object of class "B"
Slot "b":
[1] 1 2 3
Slot "a":
character(0)
(drugi przykład wykorzystuje fakt, że nienazwane argumenty new
lub B
są używane do inicjalizacji klas dziedziczonych).
To nie jest tak przyjazny dla użytkownika, aby użyć .A
lub .B
bezpośrednio, na przykład dlatego, że podpis jest tylko ...
i tak byłyby udokumentowane jako „patrz definicja szczelinami do klasy A”. To zakłóca rozdział interfejsu i implementacji, który jest siłą OOP. Również jedno lub drugie zachowanie w ostatniej części kodu (.B(.A(a=a), b=b)
lub .B(a=a, b=b)
) może nie być zamiarem. Więc zamiast zapewniać funkcję jest narażone na użytkownika, może jakiejś wstępnej masaż danych
A <- function(a=character(), ...) {
## nothing special, just a public constructor
.A(a=a, ...)
}
B <- function(b, a="hello", ...) {
a <- tolower(a) ## no SHOUTing!
.B(A(a=a), b=b) ## A's public interface; no need for B to know A's details
}
Funkcje A i B zdefiniować interfejs, zapewnić użytkownikowi wskazówki o tym, co dopuszczalne argumenty są bez związania konstruktora do definicji klasy i wykonać wstępne masowanie danych. Te ostatnie mogą sprawić, że metody initialize
będą zbędne, co jest dobre, ponieważ mają one complicated contract (powinny one być inicjatorami kopiowania i i jak widzieliśmy powyżej nienazwane argumenty mają inicjować klasy bazowe), które najbardziej ludzie się mylą.
Przeważnie są to tylko moje opinie.
Również, a właściwie nie część pytania, ".A <- setClass (" A ", reprezentacja (a =" znak "))' pozwala '.A()' lub '.A (a =" foo ")' jako konstruktorów, zamiast 'nowych (" A ")'. Używam '.A <- ...' zamiast 'A <- ...', ponieważ nadal uważam, że często będzie pisać bardziej formalny konstruktor o nazwanych argumentach, itp., Który wywołuje '.A()' jako jego ostateczny linia. –
@MartinMorgan Dzięki, niezła sztuczka! Przydałoby się zobaczyć przykład twojego bardziej formalnego konstruktora za pomocą '.A()', nie wiesz dlaczego wolisz to od 'nowego (" A ")' ?. – cboettig