Al transformar el código Java en código Ceilán, a veces encuentro algunos constructores de clase Java que confunden la verificación e inicialización. Usemos un ejemplo de código simple pero artificial para ilustrar lo que quiero explicar.
Algún código malo
Considere la siguiente clase Java. (Hombre, no escribas dicho código en casa)
Período de clase pública {fecha de inicio de fecha final privada; Fecha final privada End Data; // Devuelve nulo si la cadena dada // no representa una fecha válida de fecha privada parsedate (fecha de cadena) {...} período público (string start, string end) {startDate = parsedate (inicio); enddate = parsedate (final); } public boolean isValid () {return startDate! = null && enddate! = null; } fecha pública getStartDate () {if (startDate == null) tirar nueva ilegalstateException (); return startDate; } fecha pública getendDate () {if (endDate == null) tirar nueva ilegalstateException (); devolver end date; }}Oye, lo he advertido antes, es artificial. Sin embargo, en realidad no es raro encontrar algo como esto en el código Java real.
El problema aquí es que incluso si falla la verificación de los parámetros de entrada (en el método oculto parsedate ()), aún obtendremos una instancia de período. Pero el período que obtenemos no es un estado "válido". Estrictamente hablando, ¿a qué me refiero?
Bueno, si un objeto no puede responder significativamente a una operación pública, diría que está en un estado no válido. En este ejemplo, getStartDate () y getenddate () arroje una excepción de IllegalStateException, que es un caso que no creo que sea "significativo".
Mirando este ejemplo, por otro lado, al diseñar el período, hemos fallado en la seguridad de los tipos aquí. Las excepciones no controladas representan una "VOIDA" en el sistema de tipos. Por lo tanto, un mejor diseño de tipo de período de período sería un no uso de excepciones no controladas; en este ejemplo, IllegalStateException no se arroja.
(De hecho, en código real, es más probable que encuentre un método getStartDate () que no verifique si hay nulo, después de esta línea de código causará una excepción de NullPointerException, que es aún peor).
Podemos convertir fácilmente la clase de período anterior en una clase de forma de Ceilán:
Período de clase compartida (string start, string end) {// Devuelve nulo si la cadena dada // no representa una fecha válida? parsedate (fecha de cadena) => ...;; valor maybestartDate = parsedate (inicio); valor quizás thensenddate = parsedate (final); boolean compartido válido => MayBestartDate existe && quizás existe; Fecha compartida StartDate {Afirmar (existe MayBeStartDate); regresar MayBestartDate; } fecha de fecha compartida enddate {afirmar (existe MayBeStartDate); regresar MayBestartDate; } fecha de fecha compartida enddate {afirmar (existe quizás thensendDate); devolver quizásenddate; }}Por supuesto, este código también encontrará los mismos problemas que el código Java original. Dos símbolos de afirmación nos gritaron, había un problema en el tipo de seguridad del código.
Hacer mejor el código Java
¿Cómo mejoramos este código en Java? Bueno, ¡aquí hay un ejemplo de las excepciones revisadas criticadas de Java que son muy razonables de resolver! Podemos modificar ligeramente el período para lanzar una excepción verificada de su constructor:
Período de clase pública {fecha de inicio de fecha final privada; Fecha final privada End Data; // lanza si la cadena dada // no representa una fecha válida fecha privada parsedate (fecha de cadena) lanza dateFormateException {...} período público (string start, string end) lanza dateFormateException {startDate = parsedate (inicio); enddate = parsedate (final); } fecha pública getStartDate () {return startDate; } fecha pública getenddate () {return enddate; }}Ahora, con esta solución, no obtendremos un período en un estado no válido. El compilador manejará el código que instancia el período para manejar entradas no válidas, lo que captará una excepción de DateFormateException.
intente {período p = nuevo período (inicio, final); ...} catch (dateFormateException dfe) {...}Este es un uso agradable, perfecto y correcto de las excepciones verificadas, y desafortunadamente rara vez veo el código Java usando excepciones verificadas como la anterior.
Hacer mejor el código de Ceilán
Entonces, ¿qué hay de Ceilán? Ceylon no tiene excepciones verificadas, por lo que necesitamos encontrar una solución diferente. Por lo general, en una situación en la que Java llama a una función y lanza una excepción verificada, Ceylon llama a la función y devuelve un tipo de sindicato. Debido a que la inicialización de una clase no devuelve ningún tipo, excepto la clase misma, necesitamos extraer alguna lógica de inicialización/verificación mixta para que sea una función de fábrica.
// Devuelve dateFormaterror Si la cadena dada // no representa una fatínea válida | dateFormaterror parsedate (string date) => ...; período compartido | dateformaterror parseperiod (string start, end de cadena) {valor inicio = parsedate (inicio); if (es dateFormaterror startDate) {return startDate; } valor enddate = parsedate (final); if (is dateFormaterror enddate) {return enddate; } Período de retorno (startDate, enddate);} Período de clase compartida (inicioDate, EndDate) {Fecha compartida StartDate; Fecha compartida enddate;}Según el sistema de tipos, la persona que llama está obligada a manejar el DateFormaterror:
valor p = parseperiod (inicio, final); if (es dateFormaterror p) {...} else {...}O, si no nos importa el problema real con un formato de fecha determinado (lo cual es posible, suponiendo que el código de inicialización en el que trabajamos le falte esa información), podemos usar nulo en lugar de dateformaterror:
// Devuelve NULL si la cadena dada // no representa una datación válida? parsedate (fecha de cadena) => ...; Período compartido? parseperiod (string start, string end) => if (exists startDate = parsedate (start), exists enddate = parsedate (end)) luego período (inicioDate, enddate) else null; shared date período (startDate, enddate) {fecha compartida startDate; Fecha compartida enddate;}El enfoque para usar funciones de fábrica es excelente, por decir lo menos, ya que generalmente tiene un mejor aislamiento entre la lógica de validación y la inicialización de objetos. Esto es especialmente útil en Ceilán, donde el compilador agrega algunas restricciones muy estrictas a la lógica de inicialización del objeto para garantizar que todas las áreas del objeto se asignen solo una vez.
Lo anterior es todo el contenido de este artículo. Espero que sea útil para el aprendizaje de todos y espero que todos apoyen más a Wulin.com.