Atualmente, estou trabalhando em uma implementação definida em JavaScript. Isso deve simular genéricos conhecidos como Java ou C #. Eu preciso de uma versão mutável disso (permite adicionar / remover valores definidos) e uma versão imutável.
Minha assinatura do construtor é assim:
new GenericSet( 'number', [ 10, 20, 30 ] );
,
// mutable set of mixed values (allows to add further values via "add")
new MutableGenericSet( '*', [ 'foo', 42, {}, /./ ] );
ou
// DataValues.prototype.equals will be used by the set for determining equality.
new GenericSet( { type: DataValue, valueComparison: 'equals' }, [ dv1, dv2, dv3 ] );
Apenas GenericSet ou implementação de um conjunto por tipo?
Inicialmente, meu principal objetivo para isso era ter conjuntos de valores de um tipo. Por exemplo, um DataValuesSet que aceitaria apenas valores de dados. Eu poderia então definir interfaces com funções que requerem uma instância DataValuesSet . Eu não podia usar herança (e acho que seria ruim de qualquer maneira), então usaria composição e teria uma instância GenericSet / MutableGenericSet internamente.
Uma abordagem alternativa seria sempre levar GenericSet, implementar e usar, o GenericSet.requireSetOfType( type )
que geraria um erro se o tipo de conjunto não fosse o necessário. Minha preocupação em fazer dessa maneira é que minhas definições de interface pareçam menos explícitas.
Toma
/**
* @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 );
// ...
}
talvez usar @param GenericSet(DataValues) dataValues
para documentar a segunda opção seria bom? Alguém vê outras implicações com a segunda abordagem ou há sugestões alternativas? Para mim, o segundo parece mais intuitivo e minha preocupação com o primeiro é que eu criaria mais sobrecarga com os construtores enquanto não vejo nenhuma vantagem clara no momento.
fonte
Respostas:
Eu costumava tentar resolver esse tipo de problema com JavaScript, o que só servia para complicar implementações de ... Bem ... Qualquer coisa. Se você não quiser usar algo como o Typecript, documente o que espera. Se as pessoas ignoram sua documentação, elas entram em território desconhecido.
Não tente forçar um pino redondo em um buraco quadrado que qualquer pessoa possa moldar em um buraco redondo. Isso é JavaScript. Abrace-o. Não lute, querida. Documente e volte a escrever código.
fonte
Eu diria que o primeiro exemplo é mais legível. Isso não implica que um erro seja gerado para o conjunto digitado incorretamente. Diz que esta função leva a
DataValueSet
. Ser explícito no seu código adiciona clareza.GenericSet.requireSetOfType
ofusca a intenção da verificação de tipo na função de impressão. Parece que está verificando itens com o tipoDataValue
.fonte
DataValuesSet
vs.GenericSet<DataValue>
. Talvez, em vez deGenericSet.requireSetOfType
nomear a funçãoGenericSet.assertSetOfType
ou similar, fosse mais claro.Dadas as opções que você apresenta, eu preferiria a primeira solução, porque é mais legível que a segunda. Mas, se você realmente deseja fazer uma solução no estilo JS, crie uma função de construtor, se os objetos são do mesmo tipo ou devem ser do tipo misto (
MakeStrictCollection
vsMakeMixedCollection
). Na função de construtor, você poderia testar, se o tipo de cada membro de sua coleção dado é do mesmo tipo ou não, e lançar um erro ou retornar um objeto de cada construtor, que tem um atributo tipo adicional"type":"strict"
vs"type":"mixed"
.Além disso:
Você deve dar uma olhada no Typescript , que pode ser o que você está procurando. E há um pacote que parece atender às suas necessidades com coleções genéricas .
fonte
MakeStrictCollection
vsMakeMixedCollection
. Em relação aos exemplos de código acima, aprintDataValues
função mudaria para verificar se o objeto fornecido erainstanceof StrictCollection
e qual era o seu tipoDataValues
.GenericSet.requireSetOfType
pode ser exatamente isso - portanto, sua sugestão parece ser apenas um detalhe de implementação daGenericSet
abordagem.