c# - qué - que es una clase en programacion
Resumen clase de instanciación en ''C#en profundidad'' (5)
Debe especificar un constructor cuando su clase de contrato describe una clase que no tiene un constructor sin parámetros. De lo contrario, es completamente innecesario. Y dado que los Contratos de Código ya implican una gran cantidad de escritura, le sugiero que deje de lado al constructor privado .
El constructor privado evita la herencia, ya que la clase derivada no puede llamar al constructor de la clase base.
Pero ya que el Code Contract Rewriter elimina todas estas clases de su código. ICaseConverterContracts
no existirá en el ensamblado compilado.
El único lugar donde se ICaseConverterContracts
su clase ICaseConverterContracts
es en el ensamblaje de contratos en bin/Debug/CodeContracts/MyProject.Contracts.dll
. Pero ese ensamblaje es solo para el verificador estático: nunca lo usarás directamente, ni siquiera tendrás una referencia a él. Por lo tanto, no es necesario tener un constructor privado allí.
La única razón por la que puedo pensar por qué Jon Skeet lo incluyó en su código es para indicar a otras personas que leen el código que la clase no está destinada a ser instanciada.
Actualmente estoy leyendo ''C # en profundidad'' por Jon Skeet y hay un ejemplo que muestra los contratos de código con una clase abstracta que implementa una interfaz que se presenta como una clase complementaria para la interfaz, en términos de contratos de código: un ''Clase de contrato para'' ( No voy a entrar en detalles sobre el funcionamiento de los Contratos de Código aquí).
La interfaz (pág. 467):
[ContractClass(typeof(ICaseConverterContracts))]
public interface ICaseConverter
{
string Convert(string text);
}
La clase abstracta:
[ContractClassFor(typeof(ICaseConverter))]
internal abstract class ICaseConverterContracts : ICaseConverter
{
public string Convert(string text)
{
Contract.Requires(text != null);
Contract.Ensures(Contract.Result<string>() != null);
return default(string); // returns dummy value
}
// prevents instantiation
private ICaseConverterContracts() { }
}
(He agregado los comentarios en el código basado en comentarios en el libro)
Mi pregunta:
¿Por qué es necesario agregar el constructor privado a esta clase abstracta cuando no se puede crear una instancia de una clase abstracta para empezar? ¿Qué no estoy recibiendo?
El ContractClassFor
es una implementación de clase ficticia para la interfaz, sin otro propósito que publicar los contratos que la interfaz exige y promete a sus consumidores. Como puede verse en la clase de contrato correspondiente, la interfaz y su clase de contrato están estrechamente acopladas. (Esta implementación un tanto torpe es probablemente porque los contratos no pueden publicarse directamente en la interfaz, ya que no se permite ninguna implementación en una interfaz). Los contratos en el ContractClassFor
dummy se aplican para todas real
implementaciones real
de la interfaz subyacente (también tenga en cuenta que solo el implemento dummy ContractClassFor
puede publicar contratos para la interfaz; de lo contrario, diferentes implementaciones podrían tener contratos diferentes, lo que realmente no tendría sentido .)
La clase ContractClassFor
nunca se crea una instancia, y a menudo encontrará implementaciones ficticias solo para que el compilador se compile, por ejemplo
public string Convert(string text)
{
Contract.Requires(text != null);
Contract.Ensures(Contract.Result<string>() != null);
return default(string); // returns dummy value
}
o
public string Convert(string text)
{
Contract.Requires(text != null);
Contract.Ensures(Contract.Result<string>() != null);
throw new NotImplementedException();
}
etc.
Marcar ese constructor como privado evita que también se cree una instancia de cualquier clase derivada:
public class Foo : ICaseConverterContracts
{
public Foo() // does not compile as the base class constructor is inaccessible
{
}
}
Esto le impide explícitamente crear una instancia de la clase ICaseConverterContracts
en cualquier circunstancia, ya que no es una clase que deba ser instanciada.
Si bien las clases abstract
no se pueden instanciar directamente, el modificador de acceso (por ejemplo, private
) en el constructor importa cuando se heredan. Al hacer que el constructor sea private
lugar del predeterminado, lo está haciendo para que no se pueda construir una clase heredada. Como este es el único constructor, efectivamente está sealed
la clase, ya que no se puede compilar ninguna clase hereditaria (a menos que esté anidada en ICaseConverterContracts
) (en C #, al menos).
Supongo que el código de Contratos de Código crea una instancia de la clase a través de la reflexión, o alguna otra forma que evite el problema de que el constructor sea private
.
Tener un constructor privado significa que no puedes heredar de esa clase.
El comportamiento es similar al de una clase sealed
, excepto que la clase todavía puede ser heredada por clases anidadas.