Actualmente estoy trabajando en una implementación establecida en JavaScript. Esto debería simular genéricos como se conoce de Java o C #. Necesito una versión mutable de eso (permite agregar / eliminar valores establecidos) y una inmutable.
Mi firma de constructor se ve así:
new GenericSet( 'number', [ 10, 20, 30 ] );
,
// mutable set of mixed values (allows to add further values via "add")
new MutableGenericSet( '*', [ 'foo', 42, {}, /./ ] );
o
// DataValues.prototype.equals will be used by the set for determining equality.
new GenericSet( { type: DataValue, valueComparison: 'equals' }, [ dv1, dv2, dv3 ] );
¿Solo GenericSet o un conjunto de implementación por tipo?
Inicialmente, mi propósito principal para esto era tener conjuntos de valores de un tipo. Por ejemplo, un DataValuesSet que solo aceptaría valores de datos. Entonces podría definir interfaces con funciones que requieren una instancia de DataValuesSet . No podía usar la herencia (y supongo que sería malo de todos modos), así que usaría composición y tendría una instancia GenericSet / MutableGenericSet internamente.
Un enfoque alternativo sería tomar siempre GenericSet e implementar y usar GenericSet.requireSetOfType( type )
lo que arrojaría un error si el tipo del conjunto no fuera el requerido. Mi preocupación por hacerlo de esta manera es que las definiciones de mi interfaz se verían menos explícitas.
Tomar
/**
* @param DataValuesSet dataValues
*/
function printDataValues( dataValues ) {
if( !( dataValues instanceof DataValuesSet ) ) {
throw Error( '...' );
}
// ...
}
vs.
/**
* @param GenericSet<DataValue>
*/
function printDataValues( dataValues ) {
// Throws error if dataValues is not a set or it it is a set with values of wrong type.
GenericSet.requireSetOfType( dataValues, DataValue );
// ...
}
tal vez usar @param GenericSet(DataValues) dataValues
para documentar la segunda opción estaría bien? ¿Alguien ve más implicaciones con el segundo enfoque o hay alguna sugerencia alternativa? Para mí, el segundo parece más intuitivo y mi preocupación con el primero es que simplemente crearía más gastos generales con los constructores, mientras que ahora no puedo ver ninguna ventaja clara.
fuente
Respuestas:
Solía intentar resolver este tipo de problemas con JavaScript, que solo servía para complicar las implementaciones de ... Bueno ... cualquier cosa. Si no desea utilizar algo como el mecanografiado, documente lo que espera. Si las personas ignoran su documentación, entran en territorio desconocido.
No intente forzar una clavija redonda en un agujero cuadrado que cualquiera pueda moldear en un agujero redondo. Eso es JavaScript. Abrázalo. No luches, bebé. Documéntelo y simplemente vuelva a escribir el código.
fuente
Yo diría que el primer ejemplo es más legible. No implica que se arroje un error para el conjunto incorrectamente escrito. Dice que esta función toma a
DataValueSet
. Ser explícito en su código agrega claridad.GenericSet.requireSetOfType
ofusca la intención de la verificación de tipo en la función de impresión. Parece que está buscando elementos con tipoDataValue
.fuente
DataValuesSet
vsGenericSet<DataValue>
. Quizás en lugar deGenericSet.requireSetOfType
nombrar la funciónGenericSet.assertSetOfType
o similar sería más claro.Dadas las opciones que presentas, preferiría la primera solución, porque es más legible que la segunda. Pero, si realmente quiere hacer una solución de estilo JS, haga una función de constructor, ya sea que los objetos sean del mismo tipo o sean de tipo mixto (
MakeStrictCollection
vsMakeMixedCollection
). En la función de constructor, que podría poner a prueba, si el tipo de cada miembro de su colección dada es del mismo tipo o no, y generará un error o devolver un objeto a partir de cada constructor, que tiene un atributo tipo adicional"type":"strict"
vs"type":"mixed"
.Aparte de eso:
Debe echar un vistazo a Typecript , que puede ser lo que está buscando. Y hay un paquete que parece satisfacer sus necesidades con colecciones genéricas .
fuente
MakeStrictCollection
vsMakeMixedCollection
. Con respecto a los ejemplos de código anteriores, laprintDataValues
función cambiaría para verificar que el objeto dado erainstanceof StrictCollection
y que su tipo eraDataValues
.GenericSet.requireSetOfType
podría ser exactamente eso; por lo tanto, su sugerencia parece ser simplemente un detalle de implementación delGenericSet
enfoque.