Guest id194 Posted June 26, 2008 at 03:55 PM Report Share #193712 Posted June 26, 2008 at 03:55 PM Tenho o seguinte: private HashMap<String, Voo> listaVoos; public Voo getVoo(String codigo) { if(this.listaVoos.containsKey(codigo)) { return this.listaVoos.get(codigo); } else { return null; } } E a classe Voo tem o construtor e override necessário ao clone() para que ao fazer: Voo v1 = new Voo(); Voo v2 = v1.clone(); Seja criada uma deep-copy (o que eu pretendo) e não shallow-copy. A minha pergunta é: O método getVoo() definido lá em cima, devolve-me uma deep ou shallow copy de um determinado Voo? Se devolver shallow, como faço para devolver deep? Link to comment Share on other sites More sharing options...
Baderous Posted June 26, 2008 at 03:57 PM Report Share #193713 Posted June 26, 2008 at 03:57 PM Shallow. O get dá-te a referência do objecto que vai aceder através do parâmetro. Para ser deep basta: return this.listaVoos.get(codigo).clone(); Link to comment Share on other sites More sharing options...
Guest id194 Posted June 26, 2008 at 04:10 PM Report Share #193716 Posted June 26, 2008 at 04:10 PM O problema é que quando eu clico no "." para me aparecer a lista de cenas que posso escrever (não estou a usar o BlueJ 👍 ) não me aprece o método clone() e se eu o adicionar na mesma e compilar, dá erro e de incompatible types o que me faz pensar que aquele clone() vai devolver um Object e não um Voo como manda o meu override feito na classe Voo. Se eu fizesse isto: return (Voo)(((Voo)this.listaVoos.get(codigo)).clone()); Já não me dava erro ao compilar e o clone aparece-me quando escrevo o ".", mas aqueles dois casts não fazem muito sentido para mim, dai a minha dúvida inicial. Deve haver outra forma de dar volta ao problema... Link to comment Share on other sites More sharing options...
Knitter Posted June 26, 2008 at 04:11 PM Report Share #193717 Posted June 26, 2008 at 04:11 PM Já te responderam mas só para acrescentar: um método get não deve devolver cópias do objecto, deve sim, devolver o objecto ou, caso se trate de uma estrutura, devolver uma nova estrutura, com os mesmos objectos e não com cópias. Esse código nem faria uma shallow nem um deep-copy, dado que ele devolve a referência para o objecto e não uma cópia da referência para o objecto, que isso sim, é uma shallow-copy. Resumido, esse código não copia o objecto, apenas o devolve. www.sergiolopes.eu Link to comment Share on other sites More sharing options...
Knitter Posted June 26, 2008 at 04:14 PM Report Share #193718 Posted June 26, 2008 at 04:14 PM (...)dá erro e de incompatible types o que me faz pensar que aquele clone() vai devolver um Object e não um Voo como manda o meu override feito na classe Voo. O teu override está errado, aliás, não é um override! Para redefinires um método tens de implementar um método com a mesma assinatura, se alteras o tipo de retorno, então alteras a assinatura, logo estás a criar um método diferente. Assim, tens dois métodos, um clone da tua classe Voo e um da classe Object, e um não é a redifinição do outro. www.sergiolopes.eu Link to comment Share on other sites More sharing options...
Guest id194 Posted June 26, 2008 at 04:39 PM Report Share #193732 Posted June 26, 2008 at 04:39 PM Então se ele devolve o objecto se calhar faz exactamente o que eu quero... Tipo, o HashMap lá em cima, regista um conjunto de objectos do Tipo Voo associado a um código e está definido uma classe chamada MapaVoos. E essa classe tem um método assim: public void addVoo(Voo voo) { this.listaVoos.put(voo.getCodigo(), (Voo)voo.clone()); } A classe Voo tem um conjunto de variáveis de instância onde algumas e, apenas algumas, são inicializadas nos construtores, outras dependem de certas acções. Por inicializadas refiro-me a atribuição de valores passados como parâmetros para o respectivo construtor, todas são inicializadas, as que dependem de certas acções são automaticamente inicializadas a null ou vazio. Depois, tenho outra classe onde tem uma variável de instância do tipo MapaVoos que é onde trato de registar os voos e bla bla. E sempre que quero adicionar um novo voo faço, por exemplo: mapaVoo.addVoo(new Voo(bla bla...)); E quando quero actualizar um voo para actualizar as tais variáveis que não foram definidas no construtor do Voo faço o seguinte: voo = mapaVoo.getVoo(codigoVoo); voo.defineOutrasVariaveis(); mapaVoo.addVoo(voo); Tendo em consideração que o put() do HashMap vai substituir o valor da chave porque a chave já existe, vai praticamente substituir o voo por um actualizado. Isto está bem então e devolver o objecto faz exactamente o que eu quero? Não sei se me expliquei bem, mas já não ando com muita cabeça para isto... Link to comment Share on other sites More sharing options...
Knitter Posted June 26, 2008 at 05:00 PM Report Share #193751 Posted June 26, 2008 at 05:00 PM Não percebi metado do que queres fazer. Vamos por partes public void addVoo(Voo voo) { this.listaVoos.put(voo.getCodigo(), (Voo)voo.clone()); } Isto só faz sentido se o que queres é colocar uma cópia do objecto voo dentro da estrutura, se o que quere é colocar o objecto então o código deveria ser apenas: public void addVoo(Voo voo) { this.listaVoos.put(voo.getCodigo(), voo); } Depois, isto voo = mapaVoo.getVoo(codigoVoo); voo.defineOutrasVariaveis(); mapaVoo.addVoo(voo); é a mesma coisa que simplesmente voo = mapaVoo.getVoo(codigoVoo); voo.defineOutrasVariaveis(); Não precisas voltar a colocar o objecto dentro da estrutura porque nunca o removeste te lá, apenas pediste o objecto, alteraste o objecto. Não percebo porque estás a criar cópias de objectos, ou porque é que estás a criar cópias de referencias, isso ainda me faz mais sentido. O que é que pretendes exactamente? www.sergiolopes.eu Link to comment Share on other sites More sharing options...
Rui Carlos Posted June 26, 2008 at 05:06 PM Report Share #193754 Posted June 26, 2008 at 05:06 PM Pois, o problema é que, pelo menos no meu tempo, o profs diziam que "dentro" da cadeira de POO, nunca havia partilhas de referências (embora dissessem que havia situações em que isso poderia não fazer sentido)... Por esse motivo, talvez deva usar o clone na introdução do valor no HashMap, e também deverá fazer o clone no getVoo, razão pela qual, precisará de voltar a inserir o voo depois de lhe alterar as variáveis. Rui Carlos Gonçalves Link to comment Share on other sites More sharing options...
Guest id194 Posted June 26, 2008 at 05:09 PM Report Share #193755 Posted June 26, 2008 at 05:09 PM Estou a criar cópias de objectos porque isso é uma das obrigações do prof. Vou-te dar um exemplo de uma classe (relativamente a esta parte não na totalidade) daquilo que o prof quer que a gente faça para qualquer classe: public class Teste { int var1; String var2; public Teste(Teste t) { this.var1 = t.getVar1(); this.var2 = t.getVar2(); } public int getVar1() { return this.var1; } public String getVar2() { return this.var2; } public Teste clone() { return new Teste(this); } } E depois, em todo o lado, devemos usar o clone e não trabalhar com a referência do objecto. Se isto é bom ou mau, neste momento não me interessa, é uma regra do prof/cadeira e eu tenho de a seguir... Quanto ao problema em si, o método getVoo() terá de ser o meu, com clone(), pelo que a minha dúvida persiste: voo = mapaVoo.getVoo(codigoVoo); voo.defineOutrasVariaveis(); mapaVoo.addVoo(voo); Isto está correcto? Link to comment Share on other sites More sharing options...
Guest id194 Posted June 26, 2008 at 05:11 PM Report Share #193756 Posted June 26, 2008 at 05:11 PM (...)e também deverá fazer o clone no getVoo, razão pela qual, precisará de voltar a inserir o voo depois de lhe alterar as variáveis. Pois, mas como disse, a única maneira que consegui fazer clone() no getVoo foi assim: (Voo)(((Voo)this.listaVoos.get(codigo)).clone()); Mas isto parece-me um bocado estúpido... Link to comment Share on other sites More sharing options...
Rui Carlos Posted June 26, 2008 at 05:17 PM Report Share #193758 Posted June 26, 2008 at 05:17 PM Parece-me que tens aí um casting a mais... Devia bastar (Voo)(this.listaVoos.get(codigo).clone()); E acredita que há castings mais estúpidos... Rui Carlos Gonçalves Link to comment Share on other sites More sharing options...
Guest id194 Posted June 26, 2008 at 05:24 PM Report Share #193759 Posted June 26, 2008 at 05:24 PM Mas lá está, eu estou a usar o JCreator e isto tem um tipo de IntelliSense, eu quando clico no "." ele mostra aquilo que eu posso fazer e até agora sempre funcionou bem, quando eu escrevo: this.listaVoos.get(codigo) E depois ".", o clone() não me aparece e se eu adiciona-lo na mesma, ele vai devolver um Object. Tudo bem, no teu código estás a fazer um casting, mas tendo em consideração que o get() do HashMap vai devolver o valor (do tipo Voo) correspondente a chave "codigo", chamar o clone() não deveria invocar o método clone codificado por mim que existe na classe Voo? Link to comment Share on other sites More sharing options...
Knitter Posted June 26, 2008 at 05:28 PM Report Share #193761 Posted June 26, 2008 at 05:28 PM Pois, o problema é que, pelo menos no meu tempo, o profs diziam que "dentro" da cadeira de POO, nunca havia partilhas de referências (embora dissessem que havia situações em que isso poderia não fazer sentido)... Eu gostava de ver é onde é que existe uma situação onde faz sentido copiares referências... a própria noção é tão estranha que nem sei o que dizer... realmente que raio de Java vos estão a ensinar, agora percebo alguns dos problemas que aqui apareceram. Estou a criar cópias de objectos porque isso é uma das obrigações do prof. Vou-te dar um exemplo de uma classe (relativamente a esta parte não na totalidade) daquilo que o prof quer que a gente faça para qualquer classe: A classe teste, é uma classe normal que respeita o encapsulamento, até aí nada de especial. Quanto ao problema em si, o método getVoo() terá de ser o meu, com clone(), pelo que a minha dúvida persiste: voo = mapaVoo.getVoo(codigoVoo); voo.defineOutrasVariaveis(); mapaVoo.addVoo(voo); Isto está correcto? Dentro do que me disseste, e se percebi bem as obrigações a que estás sujeito, sim, esse código estará correcto. Pelo menos irá funcionar, no sentido em que te dá uma referência para um objecto, te permite alterar os seus valores e te permite colocar o objecto de volta na estrutura. Pois, mas como disse, a única maneira que consegui fazer clone() no getVoo foi assim: (Voo)(((Voo)this.listaVoos.get(codigo)).clone()); Mas isto parece-me um bocado estúpido... E é 👍 , verifica se tens bem os casts. Sinceramente não sei como ajudar neste caso, muito do código que aqui apresentaram não faz grande sentido, e essa de copiar as referências ainda me parece estranha... www.sergiolopes.eu Link to comment Share on other sites More sharing options...
Guest id194 Posted June 26, 2008 at 05:38 PM Report Share #193767 Posted June 26, 2008 at 05:38 PM Se estas a dizer que o que fiz está bem, porque me estas a dizer para verificar bem os casts? Mas ninguém está a copiar as referências, eu não quero copiar as referências, mas sim uma cópia do objecto e para isso, tenho de usar o clone implementado por mim, só que o método getVoo() não estou a conseguir aplicalo ao get() do HashMap, é só esse o meu problema... Link to comment Share on other sites More sharing options...
Knitter Posted June 26, 2008 at 05:52 PM Report Share #193769 Posted June 26, 2008 at 05:52 PM O que tens de usar é o método clone redefinido por ti, e para isso tens de redefinir o método correcto, que tem de devolver um Object. Os casts fazem-se depois. Não implementas um método da API alterando a assinatura. Agora tive de olhar bem para a classe que tinhas implementado, o método clone na class teste está mal implementado. Correctamente tem de devolver um Object. O que te disse, foi que o código apresentado irá funcionar, tirando algum bug que tenhas, e como não estou a ver todo o código, apenas estou a ver alguns pedaços, é complicado detectar todos os erros. Quanto aos casts, parece-me que tens casts a mais. E desculpa mas ainda me custa perceber o que estás a fazer. Isto porque o que me parece é que estás a colocar um objecto na hash, cada vez que o vais buscar crias uma cópia desse objecto, alteras essa cópia e colocas a cópia dentro da hash novamente para substituir o objecto que lá tinhas colocado inicialmente. É isto? É que se for isto, não faz sentido nenhum, além de que, não estás a trabalhar como estruturas sincronizadas, isso é, mais um, poço de problemas. Se queres que o clone funcione correctamente, implementa-o correctamente, e isso significa não criar um método novo mas sim redefinir o que já existe. www.sergiolopes.eu Link to comment Share on other sites More sharing options...
Guest id194 Posted June 26, 2008 at 06:06 PM Report Share #193773 Posted June 26, 2008 at 06:06 PM Isto porque o que me parece é que estás a colocar um objecto na hash, cada vez que o vais buscar crias uma cópia desse objecto, alteras essa cópia e colocas a cópia dentro da hash novamente para substituir o objecto que lá tinhas colocado inicialmente. É isto? Mas lá está, é assim que tenho de fazer, não posso simplesmente usar a referência e alterar o voo e pronto, já está, não precisava de actualizar a hash. Eu sei que isto seria o correcto, mas não posso fazer nada... Se queres que o clone funcione correctamente, implementa-o correctamente, e isso significa não criar um método novo mas sim redefinir o que já existe. Mas mais uma vez, regras do prof... Se bem que aqui não tenho a certeza total se os clones devem retornar o tipo da classe ou Object... De qualquer maneira isso não deveria ser problema digo eu), eu posso ter os métodos overloaded que quiser e como tal, ele deveria usar aquele que eu quero e neste caso o meu clone e assim não precisava do cast para nada... Link to comment Share on other sites More sharing options...
Guest id194 Posted June 26, 2008 at 06:20 PM Report Share #193775 Posted June 26, 2008 at 06:20 PM Pelas razões atrás apontadas, não utilizaremos o método clone() da classe Object e vamos definir nas nossasclasses um método próprio. Se em versões anteriores de JAVA alguma complicação poderia existir com o nome de tal método, em JAVA5, com a possibilidade de o tipo de resultado de um método redefinidor ser subtipo do redefinido, então os nossos método de cópia podem chamar-se clone() e devolver um objecto do tipo da classe onde forem implementados, como se mostra nos exemplos a seguir: public Ponto2D clone() { public Pixel clone() { public Ponto3D clone() { Todos estes métodos são portanto redefinições correctas do método clone() de Object, pois têm o mesmo nome, modificador de acesso mais lato e tipo de resultado que é um subtipo de Object. Quando usados, estes métodos devolverão de imediato um objecto da mesma classe do objecto “clonado”, não sendo necesário realizar qualquer casting: Ponto2D p2 = p1.clone(); Pixel pix2 = pix1.clone(); Pequeno excerto de um PDF da cadeira... Esta é a razão pela qual os nosso métodos clone() devolvem o tipo da classe e sendo uma regra da cadeira, eu tenho de a usar se quero ter a melhor nota possível. Seja isto discutível se é boa prática ou não, não me interessa, pelo menos neste momento, talvez um dia mais tarde, neste momento não quero saber se é correcto ou não o que interessa é que é assim que tenho de fazer e como tal, continuo com o mesmo problema no método getVoo(). Link to comment Share on other sites More sharing options...
Knitter Posted June 26, 2008 at 06:24 PM Report Share #193776 Posted June 26, 2008 at 06:24 PM Não pretendo discutir se é ou não bom, não tinha, até há pouco tempo, percebido que eram restrições da forma como vos ensinam. Mas então, o código que tens, está a dar erro onde concretamente ou de que forma é que está a desviar-se do que pretendes? Podes colocar um excerto maior de código, para que perceba melhor os problemas? Ou enviar-me parte do código? www.sergiolopes.eu Link to comment Share on other sites More sharing options...
Guest id194 Posted June 26, 2008 at 06:46 PM Report Share #193790 Posted June 26, 2008 at 06:46 PM É complicado porque não faço ideia do que enviar e não está a dar erro nenhum, eu só não sei se estou a fazer as coisas direitas mas acabei de fazer um teste e se calhar até estou... não sei bem... Vamos lá ver se a gente se entende: Tipo, no HashMap tenho uma lista de objectos do Tipo Voo associado a um código do tipo String e tenho um método getVoo() que é suposto devolver uma cópia sem partilha de endereço de determinado voo de código especificado pelo que a assinatura da função será: public Voo getVoo(String codigo); Tendo em conta que a minha classe Voo é tipo a classe Teste que apresentei anteriormente, ou seja, assim: public Voo clone() { return new Voo(this); } Como é que eu codifico o método getVoo() sem que haja partilha de endereços? Teoricamente seria: this.listaVoos.get(codigo).clone(); Mas este clone está a devolver um objecto, ou seja, não é o meu clone e a minha dúvida aqui é, porquê? Para eu conseguir usar o meu clone tenho de fazer um cast assim: ((voo)this.listaVoos.get(codigo)).clone(); Mas o get() do HashMap não deveria devolver um objecto do tipo Voo? Tendo em consideração que a definição do HashMap é HashMap<String, Voo>. O que me leva ao seguinte... Experimentei codificar o método getVoo() apenas assim: return this.listaVoos.get(codigo); E tenho o seguinte código para testes: Voo v1 = AEROGEST.mapaVoo.getVoo("A"); v1.setCompanhiaArea("TAP"); AEROGEST.mapaVoo.addVoo(v1); Voo v2 = AEROGEST.mapaVoo.getVoo("A"); Consola.writeLine(v1.toString()); Consola.writeLine(v2.toString()); E o output é: VooComercial@1d58aae VooComercial@de6f34 Ou seja, está com endereços diferentes né? O que me leva a pergunta, o getVoo() devolveu uma cópia ou uma referência do Voo? O que está a azul são as minhas principais dúvidas... Algo que não sei se será importante e/ou talvez responda ás minhas dúvidas mas a classe Voo é abstracta e o seu clone está definido como public abstract Object clone() e as suas subclasses é que têm o clone definido por exemplo: public VooComercial clone() { return new VooComercial(this); }. Link to comment Share on other sites More sharing options...
Knitter Posted June 26, 2008 at 07:11 PM Report Share #193804 Posted June 26, 2008 at 07:11 PM Mas o get() do HashMap não deveria devolver um objecto do tipo Voo? Tendo em consideração que a definição do HashMap é HashMap<String, Voo>. A declaração da estrutura tem de ser HashMap<String, Voo> m = new HashMap<String, Voo>(). Se a tiveres assim, então o get terá de devolver um Voo e o clone invocado tem de ser o teu. Ou seja, está com endereços diferentes né? O que me leva a pergunta, o getVoo() devolveu uma cópia ou uma referência do Voo? Referencias diferentes são objectos diferentes, nesse sentido, os dois objectos do tipo Voo são objectos diferentes. Não sabendo mais sobre como os métodos introduzem dados nas estruturas e que mais implicações tens no código não posso ajudar muito. Algo que não sei se será importante e/ou talvez responda ás minhas dúvidas mas a classe Voo é abstracta e o seu clone está definido como public abstract Object clone() e as suas subclasses é que têm o clone definido por exemplo: public VooComercial clone() { return new VooComercial(this); }. Não existe qualquer problema em teres declarado um método como abstracto, e a classe que o define. Apenas estás a dizer que as subclasses terão de ser abstractas ou de implmentar todos o método. www.sergiolopes.eu Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now