Hacer métodos / propiedades visibles a una clase, oculto a los demás
-
23-08-2019 - |
Pregunta
Tengo un Server
clase que habla con una conexión de servidor de IRC. Contiene una lista de User
s conocidos, y las crea si es necesario.
Tengo dos problemas que afectan a la clase User
:
- Cualquier persona puede crear una instancia de un
User
. Sólo quiero la claseServer
para ser capaz de hacer esto. - Si un usuario (lo describe
User
) cambia su / su nombre (u otra información, como los canales unidas), la claseServer
puede cambiar ella misma. Sin embargo, otras clases también puede! Quiero no permitir otras clases de tocar esta información (por lo que es de sólo lectura a ellos).
¿Cómo puedo resolver estos dos problemas? En C ++, se puede resolver mediante el uso de la palabra clave friend
y haciendo que el ctor y setName
(y tal) privado.
¿Hay un C # palabra clave que puede permitir un cierto método sea accesible por una clase especificada? Esto resolvería mi problema.
Solución
Sinceramente creo que el acceso friend
que se originó en C ++ para ser un síntoma de un mal diseño. Es mejor que la fijación de su diseño.
Para empezar, a quién le importa si alguien crea un usuario? ¿Realmente importa? Lo pregunto porque parece que a veces los programadores se ven atrapados preocuparse por las cosas que simplemente no va a pasar o, si lo hacen, no importa.
Si realmente se preocupan continuación, realice una de las siguientes:
- Hacer una interfaz de usuario. Servidor puede crear una instancia de una clase privada que lo implementa; o
- Haga usuario una clase interna del servidor sin constructores públicos por lo que sólo se puede crear una instancia de servidor de la misma.
hacks Visibilidad (de los cuales los amigos en C ++ son uno y acceso a paquetes en Java son dos buenos ejemplos) simplemente están buscando problemas y no es una buena idea.
Otros consejos
Lo más cerca que en el mundo .NET para friend
es la visibilidad internal
.
Tenga en cuenta que si sus dos clases están en asambleas separadas, se puede utilizar el InternalsVisibleTo atributo para permitir la visibilidad de un montaje de las partes internas de la otra.
El rediseño de su jerarquía de clases es probablemente una solución justa a este problema. Debido a que me suena como lo que realmente necesita es una clase de usuario de sólo lectura cuando existe fuera de la clase de servidor.
Yo probablemente hacer algo como esto:
// 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.
}
A continuación, tiene las clases ServerUser creados clase de servidor, usuario de la clase del servidor para cambiar las propiedades de las clases ServerUser (como cambiar nombre de usuario), pero sólo exponer Clases de usuario con el mundo exterior.