Open PalumboN opened 5 years ago
@lspigariol @asanzo
HOLA TE QUIERO
Más allá de mi amor por el Rasta, me gustaría agregar que esta discusión se tuvo en algún momento y no recuerdo honestamente los pormenores. Busqué en las listas y en los issues pero no encontré. Lo que veo es que los abstract methods están acá hace rato, y yo siempre me sentí un poco incómodo.
Así que todo sí a este feature, salvo la pequeña aclaración de que el abstract también lo haría opcional.
Para mí los override method
, los abstract class
y los métodos abstractos son ejemplos de cosas que aclaramos en el código no porque no funcione de otra forma, sino porque nos interesa documentar. Podemos tener discusiones sobre qué de todo eso nos interesa documentar y cómo también, pero empezar por ponerlos opcional es cheto.
Pero es cierto que desde la perspectiva de un alumno ninguna de esas cosas son necesarias, y son boilerplate. Bah, salvo la honrosa excepción de los métodos abstractos, aman ponerlos en las superclases para documentar que todas abajo lo deben implementar. Lo ví mil veces, y aunque me molesta, veo el punto. Quieren una interfaz, tienen los tipos en la sangre.
Y si quieren puedo levelear la discusión a ¿Qué pasa con otra info como las interfaces? ¿No quiero también interfaces opcionales?
:bomb:
:running_man:
Me gusta que se plantee la discusión, no tengo opiniones muy fuertes... los sigo. Esto tiene que hablarse para el ROADMAP 2020, porfi recuérdenmelo para el sábado.
abstract
para clases abstractas, no hace falta que tengas métodos abstractosrequired
para el método abstracto, eso desambigua la validación: si se olvidaron las llaves Wollok tiene que tirar error (opcional). Igual permitimos hacer self.metodo()
y no definir el método si la clase es abstractaoverride
pasaría a ser opcional, en el caso en que se defina debe existir el método en la superclase? self.saraza()
y no existe ese método, la clase debe ser abstracta o ERRORabstract class Ave {
method vivirUnDia() {
self.comer()
self.volar()
}
}
class Golondrina inherits Ave {
method volar() { …}
method comer() { …}
}
Y qué va a pasar con todo el código viejo? Estalla, ¿verdad?. No me jode, pero antes que esto implementemos lo de poner la versión al root/package, así podemos hacer cosas inteligentes como las q mencionaba NicoS.
Por cierto, les amé, me sientro ultra cómodo con esto que se decidió
Bueno, entro a comentar en esto traido por un comentario de @asanzo en la discusión de qué hacer con el override
del initialize y otras yerbas. Me gustaría bajar a escrito algunas cosas que se discutieron que no encontré salvadas en ningún lado y de paso pensar un poco en voz alta:
De entrada, me gustaría que en estas decisiones no nos olvidemos de considerar a los Mixines, que no pueden instanciarse y pueden tener métodos abstractos y sobreescritos, y del sistema de tipos que, si no entiendo mal, se nutre de las definiciones de métodos abstractos. En principio nada de lo que se dijo choca con esto, pero hay algunas afirmaciones que pueden hacer un poco de ruido:
Poner la palabra abstract para hacer referencia al concepto (que hasta ahora no aparece en el lenguaje).
Poner la palabra abstract
en la Clase pero no en el Mixin (porque no la vas a poner en el Mixin porque tendrías que ponerlo siempre) medio que trastorna un poco la idea de que la palabra materializa el concepto.
Que el concepto se centra en la clase, y los métodos abstractos quedan en segundo lugar. Podríamos tener clases abstractas sin métodos abstractos, simplemente porque el dominio conlleva a no querer instanciarla.
Para mi el concepto de clase abstracta tiene más sentido cuando no puedo instanciar la clase más que cuando elijo no instanciarla. No se me ocurre una buena razón para marcar una clase como "NO INSTANCIABLE" si ya tiene todo lo que le hace falta tener para funcionar, me suena al mismo tipo de capricho que marcar las clases como final
y lleva a situaciones como tener "hojas" sin código porque "la superclase es para poner el código común".
Meh... En todo caso, cuando te falta un método que necesitás no hay nada que hacer: esa clase tiene que ser abstracta te guste o no. Por eso yo creo que el peso de la abstractez (¿?) lo carga el método, no la clase.
Marcando la clase como abstracta, podríamos decir que cualquier mensaje a self (sin método asociado) en una clase abstracta es porque se referencia a un método abstracto, sin necesidad de escribirlo.
Este me parece el punto más interesante para rumiar. Por un lado te ahorra definir mensajes abstractos, pero por otro asume que nunca tipeas mal por accidente. No sé de que astucias es capaz el sistema de tipos acá pero estoy seguro de que si hacés opcional el método abstracto el alumno promedio al que el método abstracto ayudaría no lo va a escribir. No es ni bueno ni malo, pero habrá que aprender a vivir con ello.
Por otro lado está bueno notar que toda sintaxis para denotar que una clase o método es abstract
u override
le sirve solamente a los humanos. El compilador ya sabe si estás sobreescribiendo o si podés o no instanciar o llamar a un método. El punto, entiendo yo, es cuidar al programador de si mismo. Los errores que se pueden detectar con cada término son:
required
(o sea, "soy un método abstracto"):
Evita que le pongas un cuerpo a un método que querías dejar abstracto. La verdad no me interesa.
Evita que te olvides las llaves por accidente.
Yo a esto le veo muy poquito valor. O sea, tenés que estar creando un método vacío Y olvidarte las llaves. Cuántas veces te pasa que necesitás un método vacío? Mucho más grave y frecuente me parece el caso de poner el igual Y las llaves y crear un método que retorna una lambda...
method ups() = { console.print("Profe hago un foreach y los objetos no cambian, Wollok está roto") }
Pero qué vas a hacer? O cambias la sintáxis de las lambdas o ponés una palabra reservada estalambdaesapropósito
o dejás que el pibe aprenda que no hay que programar a las 4 de la mañana.
override
(o sea, "estoy pisando un método"):
Evita que pises un método por accidente. Este caso me parece más bien improbable en un modelo en la escala en la que trabajamos en las clases. Si pisas algo por accidente es de object y, considerando los poquitos mensajes que tiene y lo mucho que se usan, es super improbable.
Evita que creas estar pisando un método, cuando en realidad lo escribiste mal
De todos los casos, este me parece el más útil. Si escribís el método initialiSe()
y te quedás pensando que funciona puede ser medio gancho. Mi opinión personal, sin embargo, es que esto no es distinto a cualquier caso de polimorfismo dónde escribis mal el mensaje.... Qué se yo, en objetos tenés que prestar atención a las firmas... Si le sumás que es opcional me parece que es esforzarse al pedo.
abstract
(o sea, "soy una clase que no debe ser instanciada"):
Te obliga a admitir que la clase no va a poder ser instanciada.
Ok... Ponele. Pero si me obligás a poner el abstract
cuando ves un método abstracto esa relación la puedo ver yo solo. Me hacés marcar la clase como abstract medio al pedo, porque en realidad no hay opción. Ese abstract
no está agragando información. Además ese mismo mensaje de error podría mostrartelo en el new
...
Evita que instancies una clase que decidiste que no debe instanciarse (aunque podrías). Oookey, pero también podés no instanciarla.
Evita poner métodos abstractos en una clase que querías instanciar Claro, pero el mundo funciona al revés, no? Yo no decido que clase voy a instanciar y reparto los métodos en función de eso, yo me doy cuenta de que necito un método en un lugar dónde no puedo implementarlo y entonces lo hago abstracto y eso me lleva a la clase abstracta. Pensar en controlar en el otro sentido no me cierra.
En fin, ninguno de estos casos me parece un aporte sustancioso. Vale hacer dos aclaraciones más:
La primera es que hacer estas keywords opcionales les quita, para mi, la poca utilidad que traen a la mesa. Si no te obligo a poner override no lo vas a poner, entonces no te va a servir para detectar nada. Si no te obligo, y además te pongo un warning, vas aprender a convivir con el amarillo y el override habrá hecho más daño que un bug.
La segunda es que, yo que soy un vago sin estudios, no comparto la idea de que una palabra clave es importante (o siquiera útil) para resaltar un concepto del lenguaje. De hecho, las palabras más importantes del paradigma son mensaje, polimorfismo, delegación y encapsulamiento y ninguna de ellas es una palabra clave en Wollok. Obviamente es importante que las palabras que sí son necesarias para la sintáxis sean elegidas con cuidado y representen correctamente la idea que hay atrás (el mejor ejemplo es que method
> function
), pero no creo que tener más palabras en la sintáxis sea mejor que tener menos. Cuanto más verbosa sea una definición más rápido se convierte en algo a lo que le pasan los ojos por encima sin leerlo.
Por eso mi propuesta sigue siendo que volemos a la mierda todas estas palabras clave y las reemplacemos con luces y colores en el IDE. Tenés un método que overridea otro? Flechita verde para arriba en el margen. Tenés un método overrideado? Flechita para abajo. Tenés un método abstracto? Te lo escribo en gris. Tenés una clase abstracta? Te la pinto de amarillo patito y te la subrayo con la palabra "abstracta" escrita en hebreo (esta podemos pensarla mejor).
El eclipse de java ya hacía todas estas cosas (y hasta te dejaba configurarlas), dan la misma información y alertas sin necesidad de ensuciar la sintáxis o agregar redundancias innecesarias y, más importante, no agregan más sintáxis que el alumno tiene que saber.
Tal vez el comentario kilométrico sugiere que estoy parado arriba de una mesa, gritando como un demente y flameando una bandera de Smalltalk, pero en realidad no tengo una postura fuerte sobre todo esto. Si deciden ir por el lado de las keywords no me opongo, pero llevo un rato largo tratando de empujar por mover complejidad de los lenguajes al IDE (de hecho, todo esto ya lo había planteado en Thin) y no quería dejar pasar la oportunidad de tirarlo de nuevo.
¡¡Holaaaa!! (gran imagen la de Nico flameando la bandera de Smalltalk, yo creo que además debería aprovechar y tatuarse en la cabeza el globo del logo).
Primero, estamos discutiendo por chirolas, estoy de acuerdo. El objetivo de este issue es minimizar la burocracia y en eso estamos de acuerdo (particularmente a mí me jode la burocracia de los los override en un template method, abajo aclaro).
Segundo, me parece interesante e importante la distinción que hace Nico sobre "chiche del IDE" y "chiche del lenguaje". Gracias por traérmelo a consideración.
Sobre la opcionalidad de las keywords: Estoy de acuerdo en no entrar a meter cosas opcionales a lo pavote. PEEeeeEEEeero siempre considerando que Wollok lo usan docentes distintos con focos distintos. Entonces si detectamos problemas reales (onda varios dicen "che, a mí el abstract
me parece central"), podemos no estar de acuerdo pero sí aceptar ponerlo opcional.
Sobre el required
: Me parece que la diferencia semántica entre method blah()
y method blah(){}
es grande, pero la diferencia sintáctica no lo es. Justamente por eso me gusta el required
. No me importa lo de olvidarte poner o no poner las llaves, quiero que pienses si querías un método abstracto o querías un método que no hace nada. Si querés documentar/tipar versus si querés establecer un comportamiento por defecto. Para mí poner la palabra te hace pensar qué querés. Podría estar equivocado igual.
Sobre el override
estoy más de acuerdo. Me molesta tener que marcar con override
las redefiniciones de un método abstracto (¡¡no estoy redefiniendo!!). Sobre los demás lugares veo pros y contras por igual de tener y no tener la palabra override. Las ventajas de esa palabra se arreglan con lucecitas del IDE.
Sobre el abstract
. Nico dice que lo que hace que "nazca" una clase abstracta son sus métodos abstractos, lo entiendo pero no creo que sea lo único. Podría pasar que no tenés un template method, por lo tanto no necesitás un método abstracto, pero aún así tenés un método que forma parte de la interfaz.
En el ejercicio de Dr House Enfermedad
es una clase abstracta y no tiene ningún template method. Y no me sirve instanciarla aunque pueda, porque le faltan métodos que son necesarios para que sea usada polimórficamente por la Persona
. Para que no se tengan que ir a leer el código, rápidamente un ejemplo mínimo:
class Persona {
var enfermedades = []
method viviUnDia() {
enfermedades.forEach { enf => enf.rompeA(self) }
}
}
class Enfermedad { // abstracta, pero no tiene métodos abstractos.
var cantCelulas = 2000
method estaActiva() = cantCelulas > 0
}
class Infecciosa inherits Enfermedad {
method rompeA(persona) { persona.subiTemperatura(cantCelulas / 1000) }
}
class Autoinmune inherits Enfermedad {
method rompeA(persona) { persona.perdeCelulas(cantCelulas) }
}
Enfermedad es abstracta porque yo la concibo abstracta, como algo que es incompleto, que no me sirve para instanciar, que está ahí para no repetir código. En este caso sí querría la palabra abstract
, porque el IDE no tiene forma de saber que en mi cabeza es abstracta. Lo que me molestaba en clase es que hablábamos de clases abstractas y de instanciación y no hablábamos de métodos abstractos, pero en Wollok no había clases abstractas y sí había métodos abstractos. Igual coincido en que es una distinción demasiado fina, y me tienta el modo simple Smalltalkero.
Esto me trae al tema de la interfaz. ¿Qué tanto los métodos abstractos son una forma de definir una interfaz y qué tanto son un requisito técnico del sistema de tipos? Que varies alumnes los usen como una forma de definir una interfaz me hace pensar que no es tan loco pensarlo así.
Todos estos bullets son una forma de justificar las definiciones y validaciones que tiró Dodine arriba. Peeeeero nada de lo que dije en este comment estoy dispuesto a defenderlo a muerte, salvo quizás lo de no necesitar el override para los métodos que redefinen un método abstracto. Así que pasando el tamiz por todo lo de arriba, creo que no aporté nada, porque lo que definió Dodine y lo que propone Nico me parece aceptable en ambos casos. :laughing: :rofl:
P.D.: Yo te levanto al hombro mientras flameás la bandera.
Respondo cosas que dijo @asanzo que me parecieron interesantes:
Entonces si detectamos problemas reales (onda varios dicen "che, a mí el abstract me parece central"), podemos no estar de acuerdo pero sí aceptar ponerlo opcional.
Absolutamente a favor de considerar una visión amplia de las necesidades de todos los docentes. Creo que lo que quiero marcar es que la opcionalidad, que puede parecer un punto medio conciliador, a veces no lo es tanto. Bah, habría que ver exactamente qué entendemos por opcionalidad, pero si un docente cree central la idea de identificar una clase como abstracta entonces hacerla opcional es medio pobre. O sea, si a mi me decís que vas a hacer opcional definir los atributos de los objetos (y que si accedés a un campo no definido lo creas dinámico, como en Ruby) te mando a la mierda. Ahora, si opcionalidad es que cada docente puede configurarlo como obligatorio si él quiere capaz es otra historia...
Me parece que la diferencia semántica entre method blah() y method blah(){} es grande, pero la diferencia sintáctica no lo es.
Sí, este es un punto excelente. Si no me queda otra que denotarlo en la sintaxis, entonces puedo comprar la idea de que el required
puede resultar más fácil de ver en un lenguaje didáctico. Ahora, para un lenguaje para uso cotidiano no me gusta tanto, porque en la variante con required el método tampoco tiene cuerpo, con lo cual el required es redundante. No sé, a mi me gusta el minimalismo, pero respeto si no es la visión de todos.
Eso no quita que creo que pintarte la firma de un color y ponerle un badge es una forma mucho más capa de decirte "Eu! Mirá que este método lo tenés que implementar, eh?".
Me molesta tener que marcar con override las redefiniciones de un método abstracto (¡¡no estoy redefiniendo!!).
Je, comparto que la palabra sugiere otra cosa y se siente un poco rara. Si me permitís jugar al abogado del diablo, podría plantear que estás redefiniendo porque en tu superclase tiene una definición de ese método, sólo que no es concreta, pero veo como ese razonamiento puede tener gusto a poco.
Dejando la semiótica a un lado, yo creo, como dije arriba, que el valor del override
está en declarar que tu definición debería matchear algo que viene de arriba, y eso permite alertarte cuando le pifias a un nombre y cuando pisas por accidente. Desde ese punto de vista es solamente cuestión de decidir de qué cosas querés proteger al programador. Si no te preocupa tanto que el pibe pifie escribiendo el nombre cuando está tratando de implementar un método abstracto entonces capaz no suma tanto.
Podría pasar que no tenés un template method, por lo tanto no necesitás un método abstracto, pero aún así tenés un método que forma parte de la interfaz.
No, bueno, acá tenemos una diferencia de definición. Tu visión de método abstracto parece derivar de las mécanicas del lenguaje (o sea, ponés un método abstracto cuándo lo tenés que definir porque sino no podés llamar a self). Mi opinión es que Enfermedad sí amerita tener un método abstracto rompeA(persona)
, no solo porque evita con mecánica que puedas instanciarla, sino porque obliga a que todas las enfermedades tengan que entender ese mensaje. Enfermedad ES abstracta; no porque no quieras instanciarla, sino porque una instancia de esa clase no podría cumplir con tu definición de lo que es una enfermedad.
En definitiva, el método abstracto atiende a esa necesidad que mencionas de que un mensaje esté en la interfaz de un tipo. Que Wollok no te obligue a definirlo es otra cosa, pero yo encuentro que es una buena práctica. Pero bueno, yo soy pro-tipado. Habrá quien difiera.
Esto me trae al tema de la interfaz. ¿Qué tanto los métodos abstractos son una forma de definir una interfaz y qué tanto son un requisito técnico del sistema de tipos? Que varies alumnes los usen como una forma de definir una interfaz me hace pensar que no es tan loco pensarlo así.
Claro, esto es lo que decía arriba: El método es la manera de materializar la interfaz y comprometerte por escrito a respetarla. Un Miixín con sólo métodos abstractos es absolutamente indistinguible de una interface de cualquier otro lenguaje. En mis clases yo uso mucho encarar un problema pensando a quién darle cuál responsabilidad antes de bajar a tierra los detalles, entonces sale mucho de poner métodos abstractos primero para tener a la vista a quién le vas a pedir qué cosa, y después el IDE solito te lleva a concretar esos métodos o definirlos en las subclases.
Muy bueno el thread. Tenía algunas cosas que me quedé pensando pero lo que me preocupa respecto a la no obligatoriedad de escribir el método abstracto es lo siguiente:
class Abstracta {
method zaraza() {
self.internalZaraza()
self.secondZaraza()
}
method secondZaraza() { ... implementación ... }
}
En este caso el validador te marcaría la llamada a internalZaraza()
con error y te sugeriría como quick fixes:
Ahora qué pasa si tenés
abstract class Abstracta {
method zaraza() {
self.internalZaraza()
self.secondZaraza()
}
method secondZaraza() { ... implementación ... }
}
class Concreta inherits Abstracta {
method otroMetodo() { ... implementación ... }
}
Esto va a tirar error en runtime y ya lo sabemos, entonces la clase Concreta debería implementar el método internalZaraza()
. El tema es cómo puedo detectar qué métodos abstractos no está implementando:
required
, es una boludezConsiderando que la propuesta dice que los métodos abstractos son opcionales, pienso ir por la opción del Rasta. No obstante, si hacemos que el IDE te genere el código para los métodos abstractos, quería ponerlo sobre la mesa. Entiendo que hay un IDE que puede hacer cosas por nosotros, el tema es que ser explícitos también ayuda al alumno a serlo (un punto que marcaba NicoS más arriba respecto a los métodos abstractos opcionales) y cuando tenés formatos que se salen del IDE (ej. imprimís el parcial para corregirlo en papel) eso también puede ayudar.
Respecto a la propuesta del override
coincido con NIcoS en que marcarlo como opcional es empezar a transitar el camino del olvido...
Bueno, se picó. Pucha, pensé que teníamos un acuerdo, ¿qué pasó?
En primer lugar habría que aclarar qué entendemos por opcional. Para mí opcional no puede ser marcarlo como warning en lugar de cómo error... eso da para toda otra charla pero en principio opcional sería que el IDE no se queje si no lo ponés. Bonus point si se puede configurar que sí de error... aunque para eso tenga sentido deberíamos poder tener un mecanismo para que une docente comparta su configuración con sus estudiantis.
En ese contexto, "ser amplio" implicaría permitir todas las variantes de clases abstractas? A saber:
Y nada de todo esto da error nunca, salvo el new de alguna clase que por algún criterio de los anteriores es abstracta. No sé, me da miedo que esa hiperflexibilidad hace que los errores no se detecten bien.
Ese lenguaje amplio, dejaría los controles a cargo del IDE, módulo que uno tenga una configuración de errores razonable... y que se pueda compartir. Si tenemos ese control de errores que está fuera del lenguaje, creo yo que es lo más moderno. Pero hay que tener ese mecanismo.
Por otro lado está la discusión de "qué es una clase abstracta", es decir, si es como dice Nico una clase que no se puede instanciar porque mecánicamente es imposible (porque le falta un pedazo) o si tiene sentido como herramienta conceptual. Croe que debemos darnos esa respuesta.
Más fácil me parece la discusión del required, porque esa yo sí la vi fallar. Es una cuestión bien técnica de la gramática del lenguaje, más que confusión de alumno por la sintaxis parecida => el que se confunde es el parser!!!! Obvio, si escribís bien el parser no se confunde, pero cuando escribís mal, el parser matchea tu método mal escrito con otra regla de la gramática y entonces en lugar de decirte "te olvidaste las llaves nabo" te dice "tu clase es abstracta" y además en la versión hiperlaxa smaltallkera, te lo dice en el lugar en que hacés new y es super confuso, no entendés por qué no la podés instanciar... y resulta que es porque te olvidaste un par de llaves.
Ese error yo lo vi muchas veces y por eso creo que es mandatorio modificar la sintaxis. El required jode poco y desambigua mucho.
Sobre el override yo tengo mis dudas, pero en tren de ser amplio ya acepté que lo hagamos opcional... es decir, si yo quiero lo escribo, si no lo escribo el compilador no se queja (con los bonus points por configurabilidad como decía arriba, pero el default es ignorar).
Si lo escribo obviamente se controla la existencia de la super clase.
Y obviamente más bonus points para las marquitas del IDE como decía NicoS.
Me parece que no vale la pena tener dos keywords distintos para cuando sobreescribo y cuando implemento un método abstracto... me parece una paja mental discutir que en realidad no estoy overrideando. El objetivo de la marca "override" es la misma en ambos casos, si querés no la pongas, si se te ocurre otra keyword mejor le damos, pero tener dos criterios distintos según si en la superclase el método es concreto o abstracto me parece mucho.
@fdodino
si los métodos abstractos no están definidos, tenemos dos opciones: recorrer la superclase en busca de llamadas a self, o la propuesta del Rasta de chequear que todas las subclases concretas implementen ese mensaje, que me parece más simple.
No entendí la segunda alternativa. ¿Cómo sabés qué mensaje tienen que implementar las subclases concretas si no está marcado como required
y no buscás los envíos de mensaje a self
?
@npasserini
Para mí opcional no puede ser marcarlo como warning en lugar de cómo error... Esto. El amarillo tiene que ser malo o no ser. Dónde empezas a entrenarlos para ignorar warnings se va todo a la mierda.
Por otro lado está la discusión de "qué es una clase abstracta", es decir, si es como dice Nico una clase que no se puede instanciar porque mecánicamente es imposible (porque le falta un pedazo) o si tiene sentido como herramienta conceptual. Croe que debemos darnos esa respuesta.
Mi propuesta concreta es que está bueno que cuando identificás que tu clase es conceptualmente abstracta la vuelvas mecánicamente abstracta, independientemente de si el lenguaje te obliga o no. Creo que se gana mucho y no cuesta tanto, pero bueno, eso va por el lado de tener los required
obligatorios...
Obvio, si escribís bien el parser no se confunde, pero cuando escribís mal, el parser matchea tu método mal escrito con otra regla de la gramática y entonces en lugar de decirte "te olvidaste las llaves nabo" te dice "tu clase es abstracta" y además en la versión hiperlaxa smaltallkera, te lo dice en el lugar en que hacés new y es super confuso, no entendés por qué no la podés instanciar... y resulta que es porque te olvidaste un par de llaves.
asdasdasd a mi no me convence mucho este argumento. O sea, sí, ese error es una mierda, pero no es la única forma posible de reportarlo. Si en ese new
que no te compila te pongo un error que dice "No podés instanciar esta clase porque es abstracta, porque el método XXX no tiene una implementación. No te habrás olvidado las llaves, no?" no te podés perder. Además, como vos decís: ¿Qué pasa si no pone el required
? Qué le va a decir el error? "Se esperaba {
o required
? No sé si eso hace que te pierdas menos. Y no es solamente que se olvidó las llaves: se olvidó todo el cuerpo del método! O estaba creando un método vacío, que no te digo que no pasa nunca pero es bastante infrecuente... Qué se yo? Para mi un pibe que no entiende lo que es una clase abstracta tampoco va a entender que tiene que escribir required
.
De todos modos reitero que agregar el required
no me jode si el corazón se los pide, pero no creo que vaya a causar un gran impacto.
Más me intriga el tema de la opcionalidad. Me gustaría escuchar los argumentos a favor de omitir los required methods. Mas allá de ahorrarte una o dos lineas no le veo ninguna ventaja y si varias complicaciones.
Lo mismo sobre marcar la clase como abstract
. Si tiene métodos required
no tenés alternativa. Ya me hiciste escribir el required
, para qué querés que te diga también abstract
. Si le faltan métodos pero no los pusiste como required
porque te molesta, no te molesta también tener que poner abstract
? Y si no le falta nada y la marcás como abstract
para que no la instancien es de puro policía. Todo opcional y justo en eso te vas a poner policía? Qué se yo... Me hace ruido. Sobre todo la opcionalidad del overrides
. Ponganse una mano en el corazón y diganme si creen que sus pibes usarían overrides
si no fuera obligatorio...
Ahí es donde, para mi, volar la keyword y mostrar luces en el IDE le gana a opcionalidad. Yo te doy el feedback con colores SIEMPRE y vos no tenés que escribir nada. Entonces no dependo de tu cooperación para contarte lo que pasa. Mientras no te interese no le des bola, pero cuando hayas roto algo los colores van a estar ahí pero va a ser tarde para ponerte a escribir los overrides.
Mierda, estoy muy verborrágico. Les juro que con todo esto estoy re en plan "hagamos lo que más les guste", pero los extraño y lo canalizo mal.
Bueno, solo vengo a contestar que
Fer decía: si los métodos abstractos no están definidos, tenemos dos opciones: recorrer la superclase en busca de llamadas a self, o la propuesta del Rasta de chequear que todas las subclases concretas implementen ese mensaje, que me parece más simple.
NicoS: No entendí la segunda alternativa. ¿Cómo sabés qué mensaje tienen que implementar las subclases concretas si no está marcado como required y no buscás los envíos de mensaje a self?
El tema de no escribir el método abstracto a mí me preocupa para cosas como ésta:
class A {
method template() {
self.operationA() // abstracto
self.operationB()
}
method operationB() {}
}
class B inherits A {
method operationC() {} // originalmente tenía un typo
}
es decir, cómo valido que operationA
no está implementado en B. Una solución es que la validación se pare en envíos de mensajes del tipo self.operationA()
, con lo cual se podría validar que
Esto para no tener que detectar los métodos abstractos haciendo un análisis del código. No se, en un par de días voy a armar la especificación de lo que escribí en este ticket más arriba, a mí tampoco me termina de convencer no escribir los métodos abstractos: por motivos didácticos porque les alumnes así bajan a tierra una decisión de diseño y porque eso facilita validar muchas más cosas.
Lo segundo que podemos hacer en febrero es retomar las reuniones para ayudar a consensuar esas especificaciones.
en febrero los leo y comento... aunque mi punto de vista sobre el tema ya está escrito por allí...
El mar, 19 de ene. de 2021 a la(s) 09:01, Fernando Dodino ( notifications@github.com) escribió:
Bueno, solo vengo a contestar que
Fer decía: si los métodos abstractos no están definidos, tenemos dos opciones: recorrer la superclase en busca de llamadas a self, o la propuesta del Rasta de chequear que todas las subclases concretas implementen ese mensaje, que me parece más simple.
NicoS: No entendí la segunda alternativa. ¿Cómo sabés qué mensaje tienen que implementar las subclases concretas si no está marcado como required y no buscás los envíos de mensaje a self?
El tema de no escribir el método abstracto a mí me preocupa para cosas como ésta:
class A {
method template() {
self.operationA() // abstracto self.operationB()
}
method operationB() {}
}
class B inherits A {
override method operationC() {}
}
es decir, cómo valido que operationA no está implementado en B. Una solución es que la validación se pare en envíos de mensajes del tipo self.operationA(), con lo cual se podría validar que
- el método exista
- o la clase sea abstracta (y como chiche, que todas las subclases implementen ese nombre del método)
Esto para no tener que detectar los métodos abstractos haciendo un análisis del código. No se, en un par de días voy a armar la especificación de lo que escribí en este ticket más arriba, a mí tampoco me termina de convencer no escribir los métodos abstractos: por motivos didácticos porque les alumnes así bajan a tierra una decisión de diseño y porque eso facilita validar muchas más cosas.
Lo segundo que podemos hacer en febrero es retomar las reuniones para ayudar a consensuar esas especificaciones.
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/uqbar-project/wollok/issues/1861#issuecomment-762797488, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACZRXG2QUCN2P22JCCDN3KDS2VYAJANCNFSM4JGQZMZQ .
TODO: Armar un documento donde especifiquemos la definición (basarnos en https://github.com/uqbar-project/wollok/issues/1861#issuecomment-674606998)
Decidimos en la reunión de hoy
abstract
a los métodos, tampoco sobre las clases abstractas que podrían reemplazarse por mixines a futuro => queda la definición como está hasta ahora
La falta de métodos abstractos ahora se marcan como ERROR:
Pero con unos profes decíamos que debería ser WARN, ya que se puede ejecutar, y tendría el mismo nivel que NO marcar el método como override:
Yyyyy, ya que estamos, para estos casos donde le envío un mensaje a self que no tiene el método, PERO que aparece en todas las subclases, podríamos agregar un quick fix para implementar el método abstracto directamente (y que sea la primera opción! :P).
También salió una propuesta de no necesitar los métodos abstractos y directamente marcar la clase como abstracta. Había un doc con eso, pero entre las cosas que me convencieron era que:
abstract
para hacer referencia al concepto (que hasta ahora no aparece en el lenguaje).