por llamar ejemplo defecto como scala macros private-constructor

scala - llamar - Usando constructor privado en una macro



constructor por defecto java (2)

Desafortunadamente para lo que estás tratando de lograr, las macros no funcionan de esta manera. Simplemente manipulan el AST en tiempo de compilación. Cualquiera que sea el resultado final, siempre es algo que podrías haber escrito literalmente en Scala (sin la macro).

Por lo tanto, para restringir los valores posibles de PosInt , necesitará una verificación de tiempo de ejecución en algún lugar, ya sea en un constructor público o en un método de fábrica en el objeto complementario.

Si las excepciones de tiempo de ejecución no son aceptables para usted, entonces un posible enfoque sería:

  • Hacer el constructor privado en la clase.
  • Proporcione (por ejemplo) un método de create en el objeto complementario que devuelva la Option[PosInt] (o Try[PosInt] , o algún otro tipo de su elección que le permita expresar un "error" cuando el argumento está fuera de rango).
  • Proporcione un método de apply en el objeto complementario similar a su ejemplo, que verifique en el momento de la compilación que el argumento está dentro del rango y luego devuelve un árbol de expresiones que simplemente llama a create(x).get .

Llamar a .get en la opción es aceptable en este caso porque está seguro de que nunca será None .

El inconveniente es que tiene que repetir la comprobación dos veces: una vez en tiempo de compilación y una vez en tiempo de ejecución.

Quiero usar un constructor privado en una macro. Este ejemplo es un entero positivo, pero el patrón básico no solo se puede usar para otros tipos numéricos como los números pares, sino también para los tipos derivados de cadenas como direcciones de correo electrónico o un nombre de directorio. Al hacer que el constructor sea privado, al usuario se le niega la oportunidad de hacer un tipo ilegal. Tengo el siguiente código:

object PosInt { import language.experimental.macros import reflect.runtime.universe._ import reflect.macros.Context def op(inp: Int): Option[PosInt] = if (inp > 0) Some(new PosInt(inp)) else None def apply(param: Int): PosInt = macro apply_impl def apply_impl(c: Context)(param: c.Expr[Int]): c.Expr[PosInt] = { import c.universe._ param match { case Expr(Literal(i)) if (i.value.asInstanceOf[Int] > 0) => case Expr(Literal(i)) if (i.value.asInstanceOf[Int] == 0) => c.abort(c.enclosingPosition, "0 is not a positive integer") case Expr(Literal(i)) => c.abort(c.enclosingPosition, "is not a positive integer") case _ => c.abort(c.enclosingPosition, "Not a Literal") } reify{new PosInt(param.splice)} } } class PosInt (val value: Int) extends AnyVal

Sin embargo, si hago que el Constructor PosInt sea privado, aunque la Macro se compile como se esperaba, recibo un error si intento usar la macro. No puedo averiguar cómo construir el árbol de expresiones manualmente, pero no estoy seguro de que eso ayude de todos modos. ¿Hay alguna manera puedo hacer esto?

Aún no puede usar un constructor privado incluso si PosInt no es una clase de valor. Aceptaré una respuesta que no use una clase de valor. La desventaja de las clases de valor es que obtienen el borrado de tipo. Además, las clases que me interesan como subconjuntos de coordenadas 2d no se pueden implementar como clases de valor de todos modos. En realidad no me interesan los enteros positivos, solo los uso como un simple banco de pruebas. Estoy usando Scala 2.11M5. Scala 2.11 tendrá la adición de la característica quasiquotes. Todavía no he aprendido a usar las cuasicotas, ya que todo el material en este momento parece asumir una familiaridad con Macro Paradise, que no tengo.


No soy un experto, pero pensé que le daría una oportunidad ... En Java, el alcance de un constructor privado se limita a la misma clase ... por lo que el objeto PosInt tendría que moverse al alcance de la misma clase de la que se llama. Dicho esto, encontré un artículo que muestra dos formas en que puede evitar que se herede el objeto @ http://www.developer.com/java/other/article.php/3109251/Stopping-Your-Class-from-Being-Inherited-in-Java-the-Official-Way-and-the-Unofficial-Way.htm

Describe el uso de la palabra clave "final" en la declaración de clase para evitar que se herede. Esa es la forma "oficial". La forma "no oficial" es hacer que el constructor sea privado, pero agregar un método estático público que devuelva un objeto de la clase ...

Sí, lo sé, es una vieja pregunta ... pero quedó sin respuesta. Nunca se sabe cuándo una pregunta antigua será el principal éxito en los resultados de búsqueda de alguien ...