Сделайте методы/свойства видимыми для одного класса и скрытыми для других.
-
23-08-2019 - |
Вопрос
у меня есть класс Server
который говорит с серверным соединением для IRC.Он содержит список известных User
s и создает их по мере необходимости.
У меня есть две проблемы, связанные с User
сорт:
- Любой может создать экземпляр
User
.Я хочу толькоServer
класс, чтобы иметь возможность это сделать. - Если пользователь (вещь
User
описывает) меняет свое имя (или другую информацию, например, присоединенные каналы),Server
класс может изменить его сам.Однако другие классы тоже могут!Я хочу запретить другим классам трогать эту информацию (сделав ее доступной только для них).
Как я могу решить эти две проблемы?В C++ эту проблему можно решить, используя friend
ключевое слово и создание ctor и setName
(и такое) частное.
Существует ли ключевое слово C#, которое может обеспечить доступность определенного метода для указанного класса?Это решило бы мою проблему.
Решение
Честно говоря, я нахожу friend
доступ, исходящий из C++, является симптомом плохого дизайна.Лучше поправьте свой дизайн.
Для начала, кого действительно волнует, создаст ли кто-нибудь Пользователя?Имеет ли это значение?Я спрашиваю об этом, потому что кажется, что иногда мы, программисты, беспокоимся о вещах, которые просто не произойдут, а если и произойдут, то это не имеет значения.
Если вас действительно это волнует, сделайте одно из следующих действий:
- Сделайте пользователя интерфейсом.Сервер может создать экземпляр частного класса, который его реализует;или
- Сделайте User внутренним классом Server без общедоступных конструкторов, чтобы только Сервер мог создавать его экземпляры.
Взломы видимости (одним из которых являются друзья в C++, а хорошие примеры — доступ к пакетам в Java) просто напрашиваются на неприятности, а не являются хорошей идеей.
Другие советы
Самый близкий в мире .NET к friend
это internal
видимость.
Обратите внимание: если ваши два класса находятся в разных сборках, вы можете использовать ВнутренностиVisibleTo атрибут, позволяющий одной сборке видеть внутренние части другой.
Перепроектирование иерархии классов, вероятно, является справедливым решением этой проблемы.Потому что мне кажется, что вам действительно нужен класс User, доступный только для чтения, если он существует вне класса Server.
Я бы, наверное, сделал что-то вроде этого:
// An abstract base class. This is what I'd use outside the
// Server class. It's abstract, so it can't be instantiated
// on its own, and it only has getters for the properties.
public abstract class User
{
protected User()
{
}
public string Name { get;}
// Other get-only properties
}
public class ServerUser : User
{
public ServerUser()
{
}
public string Name { get; set;}
// Other properties.
}
Затем класс Server создаст классы ServerUser, а пользователь класса Server изменит свойства классов ServerUser (например, изменит имя пользователя), но откроет только классы User для внешнего мира.