ja lubię oznaczać ten seter jako wewnętrzny w interfejsie, więc nie ma szans, że ktoś implementuje ICustomer, a ktoś poza zespołem modyfikuje te właściwości. Czy jest to dobry sposób na zrobienie tego?
Nie. Użytkownicy nieruchomości to zawsze publicznych, niestety. Dodatkowo, kłopoty z poziomami dostępu do właściwości, w których część jest określona na interfejsie, stają się bolesne, IIRC. Co ty może zrobić to w ten sposób:
public interface ICustomer
{
string FirstName { get; }
string SecondName { get; }
}
internal interface ICustomerWithSetMethods : ICustomer
{
void SetFirstName(string name);
void SetLastName(string name);
}
public class Customer : ICustomerWithSetMethods
Następnie z poza to będzie wyglądać Customer
realizuje tylko ICustomer
, ale z wewnątrz Twój kod będzie widać, że realizuje ICustomerWithSetMethods
.
Niestety to nie gra ładnie, czy API musi deklarować żadnych metod publicznych, gdzie by naprawdę jak po prostu zadeklarować typ zwracanej ICustomer
, ale musisz wiedzieć, że faktycznie to zawsze ICustomerWithSetMethods
.
Zakładając, że nadal chcą, aby umożliwić wielu implementacji, można potencjalnie iść do klasy abstrakcyjnej Zamiast:
public abstract class CustomerBase
{
public abstract string FirstName { get; }
public abstract string LastName { get; }
internal abstract void SetFirstName(string name);
internal abstract void SetLastName(string name);
}
teraz mamy niewielki osobliwość, że nikt poza zespołem może przedłużyć swój CustomerBase
, ponieważ nie są metodami abstrakcyjnymi, które musiałyby zastąpić, a które nie mogą nawet zobaczyć - ale oznacza to, że możesz używać CustomerBase
wszędzie w swoim API.
To podejście przyjęliśmy w Noda Time dla systemów kalendarzy w końcu - I blogged about it, kiedy po raz pierwszy wymyśliłem plan. I ogólnie preferuję interfejsy do klas abstrakcyjnych, ale korzyści tutaj były znaczące.
Dzięki za pomoc. Jeśli jednak to zrobię, a klasa konsumująca korzysta z ICustomer, nie może dotrzeć do setera. – larryq
@larryq To jest cały punkt, ponieważ interfejs nie zobowiązuje się do ustawiacza. Jeśli chcesz zaimplementować drugi wewnętrzny interfejs, który doda setera, możesz. Często mam serię interfejsów: to jest prawdziwy przykład: 'IDimensionedMap' zatwierdza tylko wymiary jednostki 2D; 'IReadMap' z czytelnymi właściwościami,' IReadMap: IDimensionedMap' dla map tylko do odczytu lub obliczonych, a następnie 'IWriteMap: IReadMap'. Ale jest to złożona rodzina rozszerzalnych klas użytkowych. (Są to 2d przestrzenie Hilberta, a nie słowniki, jeśli jesteś ciekawy.) – SAJ14SAJ
@larryq Chociaż nie jestem pewien, czy tego potrzebujesz, czy nie, dodałem alternatywną implementację, w której interfejs definiuje metodę wewnętrznego zestawu. – Servy