Add objects of different types in the same vector

Asked

Viewed 236 times

0

I can’t add class Video within the vector.

public class SongDriver {
    public static void main(String[] args) {
        Playlist lista = new Playlist();
        Musica num1 =new Musica("Agua de beber","Antonio Carlos Jobim","Astrud Gilberto", 140);
        Musica num2 =new Musica("O mar serenou","Candeia"," Clara Nunes", 179);
        Musica num3 =new Musica("Rapaz Folgado","Noel Rosa"," Martinho da Vila Mart'nália",180);

        Video num4 = new Video("Musica"," Despacito", " Luis Fonsi",5926796,280);

        lista.add(num1);
        lista.add(num2);
        lista.add(num3);
        lista.add(num4);


        lista.print();

    }
    public static class Playlist{

        private Musica []musicas;
        private int cont;

        public Playlist(){
            musicas = new Musica[1000];
            cont = 0;
        }
        public void add(Musica a){
            if(cont==musicas.length){
                System.out.println("ERROR: playlist atingiu sua quantidade máxima de itens.");
            }
            musicas[cont]= a;
            cont++;
        }
        public void add(Video b){
            if(cont==musicas.length){
                System.out.println("ERROR: playlist atingiu sua quantidade máxima de itens.");
            }
            musicas[cont]= b;
            cont++;
        }
        public Musica get(int i){
            if(cont> i){
                return musicas[i];
            } else {
                return null;
            }
        }
        public void print(){
            String result="Total de Musicas e Videos Alocados = "+cont+"\n";
            for(int i =0; i <cont; i++){
                result+=( i +" => "+musicas[i]+"\n");
            }
            result+="Tempo Total da PlayList: "+formatoTotalTempo();
            System.out.println(result.toString());
        }
        public int totalTempo(){
            int totalTempo=0;
            for(int i =0; i <cont; i++){
                totalTempo+=musicas[i].getDuracao();
            }
            return totalTempo;
        }

        public String formatoTotalTempo(){
            return formatoTempo(totalTempo());
        }
    }

    public static class Musica{

        public String nome;
        public String interprete;
        public String compositor;
        public int duracao;

        public Musica(String musicaNome,String interprteNome,String compositorNome,int tamanhoDuracao){
            this.nome=musicaNome;
            this.interprete=interprteNome;
            this.compositor=compositorNome;
            this.duracao=tamanhoDuracao;
        }

        public void setNome(String musicaNome){
            nome=musicaNome;
        }

        public String getNome(){
            return nome;
        }

        public void setInterprte(String interpreteNome){
            interprete=interpreteNome;
        }

        public String getInterprete(){
            return interprete;
        }

        public void setCompositor(String compositorNome){
            compositor=compositorNome;
        }

        public String getCompositor(){
            return compositor;
        }

        public void setDuracao(int tamanhoDuracao){
            duracao = tamanhoDuracao;
        }
        public int getDuracao(){
            return duracao;
        }
        public String toString(){
            return"Nome: "+getNome()+", Interprete:"+getInterprete()
                +", Compositor:"+getCompositor()+", Duracao: "+formatoTempo(getDuracao());
        }
    }
    public static class Video{
        String titulo;
        String assunto;
        String canal;
        int visualizacoes;
        long duracao_video;

        public Video(String tituloNome,String assuntoNome,String canalNome,int visualizacoes_video, long tempo_video){
            this.titulo = tituloNome;
            this.assunto = assuntoNome;
            this.canal = canalNome;
            this.visualizacoes = visualizacoes_video;
            this.duracao_video= tempo_video;
        }
        public void setTitulo(String tituloNome){
            titulo = tituloNome;
        }

        public String getTitulo(){
            return titulo;
        }
        public void setAssunto(String assuntoNome){
            assunto = assuntoNome;
        }

        public String getAssunto(){
            return assunto;
        }
        public void setCanal(String canalNome){
            canal = canalNome;
        }

        public String getCanal(){
            return canal;
        }
        public void setVisualizacoes(int visualizacoes_video) {
            visualizacoes = visualizacoes_video;
        }
        public int getVisualizacoes() {
            return visualizacoes;
        }
        public void setDuracao_video(long tempo_video) {
            duracao_video = tempo_video;
        }
        public long getDuracao_video() {
            return duracao_video;
        }
        public String toString(){
            return"Titulo: "+getTitulo()+", Assunto:"+getAssunto()+", Canal:"+getCanal()+
                    ", Visualizações: "+getVisualizacoes()+" Duração do video:"+formatoTempo(getDuracao_video());
        }

    }
    public static String formatoTempo(long tempo){
        int hora = 60;
        int minuto = 60;
        long h= tempo /hora;
        long m= tempo % minuto;
            return String.format("%02dh %02dmin", h, m);
    }

}
  • It won’t work because you’re trying to add one Video in an array of Musica. Since the two classes have no relation to each other, their types are incompatible and it is not possible to place one in an array that only has the other. Create another array just for Video (actually, there are other solutions, like refactoring classes, creating an interface Playable, for example, for any type of "touchable" media, etc). But for now, having another array should suffice...

  • Hkotsubo, how do I create a Generic vector for both music and video classes.

1 answer

3


The problem is that Musica and Video are different classes that have no relation to each other. Therefore, when trying to place a Video in an array of Musica, gives build error. There are some alternatives to solve this problem.

Note: I created each class in a file .java separate, so in my code below they are not static. Maybe you have put everything in a file just "for ease", but create nested classes has very specific uses which does not seem to be the case here. So I suggest you separate each class into its own file .java.


Use another array to Video

This is a solution that requires no class changes Musica and Video. Just keep a separate array for each of them. As you are controlling the amount of music with another variable, you will need one more for the videos as well (and I changed the name of the counters to something more significant).

public class Playlist {
    private Musica[] musicas;
    private Video[] videos; // novo array só para vídeos
    // manter um contador para cada tipo de mídia
    private int qtdMusicas;
    private int qtdVideos;

    public Playlist() {
        musicas = new Musica[1000];
        videos = new Video[1000];
        qtdMusicas = 0;
        qtdVideos = 0;
    }

    public void add(Musica a) {
        if (qtdMusicas == musicas.length) {
            System.out.println("ERROR: playlist atingiu sua quantidade máxima de músicas.");
        }
        musicas[qtdMusicas] = a;
        qtdMusicas++;
    }

    public void add(Video b) {
        if (qtdVideos == videos.length) {
            System.out.println("ERROR: playlist atingiu sua quantidade máxima de vídeos.");
        }
        videos[qtdVideos] = b;
        qtdVideos++;
    }
}

Obviously you will need to add a method getVideo, and I would also change the name of the method get current to getMusica. The method print you should also scroll through the video array right after the loop existing in the music array.

But this solution is not very good because it duplicates a lot of code: the algorithm for adding, obtaining and printing music and videos is pretty much the same. And if in the future you want to add another class (for example, Filme), will have to duplicate code again.

Perhaps it is better to generalise the solution, but this will require a change in the classes.


Generalizing...

If you want your Playlist has both songs and videos, can make both classes Video and Musica share some characteristic that allows to group them. In this case, both can be "played" in a player media. So I can create a interface representing this characteristic:

// representa qualquer coisa que pode ser "tocada" em um player
public interface Playable {
    public String getNome();
    public int getDuracao();
}

In this case, the interface Playable represents "something that can be touched on a player". I also defined the methods getNome() and getDuracao(), but note that these methods have no code. The interface only defines what one Playable does, but does not as this is done.

Now just make sure that Musica and Video are "things that can be touched in a player". In other words, both classes should implement the interface Playable:

public class Musica implements Playable {
    // o resto da classe permanece igual
}

As the class Musica already has the methods getNome() and getDuracao() (and they return respectively a String and a int, as defined in the interface), there is no need to do anything else. Already the class Video will need some adaptations, since it does not have these methods (below I put only the snippets that I changed):

public class Video implements Playable {
    // mudei a variável duracao_video, pois é redundante (ela faz parte de Video, então claramente é a duração do vídeo)
    int duracao; // mudei para int, o tempo é em minutos, não precisa de long

    public Video(String tituloNome, String assuntoNome, String canalNome,
                 int visualizacoes, int tempo) {
        ....
        this.duracao = tempoVideo;
    }

    @Override
    public String getNome() {
        return this.titulo; // o nome do vídeo é o seu título
    }
    public void setDuracao(int tempo) {
        duracao = tempo;
    }

    @Override
    public int getDuracao() {
        return this.duracao;
    }
}

I changed a few things: since time is in minutes (from what I understand), you don’t need to use a long. A int supports up to just over 2 billion, which is enough for any video.

I also changed the name of duracao_video for duracao. If the duration belongs to the class Video, it is redundant to say that this is the duration of the video. Another point is to avoid nomes_de_variaveis_assim, since the java convention is to use nomesDeVariaveisAssim.


Well, now that so much Musica how much Video sane Playable, we can change our array:

public class Playlist {
    private Playable[] items;
    private int qtdItens;

    public Playlist() {
        items = new Playable[1000];
        qtdItens = 0;
    }

    public void add(Playable item) {
        if (qtdItens == items.length) {
            System.out.println("ERROR: playlist atingiu sua quantidade máxima de itens.");
        }
        items[qtdItens] = item;
        qtdItens++;
    }

    public Playable get(int i) {
        if (qtdItens > i) {
            return items[i];
        } else {
            return null;
        }
    }

    public void print() {
        String result = "Total de Musicas e Videos Alocados = " + qtdItens + "\n";
        for (int i = 0; i < qtdItens; i++) {
            result += (i + " => " + items[i] + "\n");
        }
        result += "Tempo Total da PlayList: " + formatoTotalTempo();
        System.out.println(result.toString());
    }

    public int totalTempo() {
        int totalTempo = 0;
        for (int i = 0; i < qtdItens; i++) {
            totalTempo += items[i].getDuracao();
        }
        return totalTempo;
    }

    public String formatoTotalTempo() {
        return formatoTempo(totalTempo());
    }
}

Notice that now I only work with Playable, i.e., the array will accept any class that implements the interface Playable. Then I can add Musica, Video and any other class I create in the future (provided that it implements Playable).


Next steps

This is just an introduction and serves as the first steps to better model your classes. But I suggest studying in depth polymorphism, class modeling and the Java interface and abstract class engine itself. It’s too broad to broach here, so I leave just one more "bonus tip".

Instead of an array, you can use java.util.List, because then you don’t have to keep track of the number of items, as the list itself increases its size as needed. The modified class would look like this:

import java.util.ArrayList;
import java.util.List;

public class Playlist {
    private List<Playable> items;

    public Playlist() {
        this.items = new ArrayList<>(); // não precisa dizer o tamanho, a lista controla isso para você
    }

    public void add(Playable item) {
        if (this.items.size() == 1000) { // se quiser, ainda pode limitar a quantidade máxima (opcional)
            System.out.println("ERROR: playlist atingiu sua quantidade máxima de itens.");
        }
        this.items.add(item);
    }

    public Playable get(int i) {
        if (i > this.items.size()) {
            return null;
        }
        return this.items.get(i);
    }

    public void print() {
        String result = "Total de Musicas e Videos Alocados = " + this.items.size() + "\n";
        for (int i = 0; i < this.items.size(); i++) {
            result += (i + " => " + items.get(i) + "\n");
        }
        result += "Tempo Total da PlayList: " + formatoTotalTempo();
        System.out.println(result.toString());
    }

    public int totalTempo() {
        int totalTempo = 0;
        for (Playable item : items) {
            totalTempo += item.getDuracao();
        }
        return totalTempo;
    }

    public String formatoTotalTempo() {
        return formatoTempo(totalTempo());
    }
}

Another detail is that if you use the method get, will get a Playable, and to know if it is a song or a video, you will have to use instanceof and do the cast:

Playable item = lista.get(0);
// testar o tipo de Playable retornado
if (item instanceof Musica) {
    Musica musica = (Musica) item;
    // usar a Musica
} else if (item instanceof Video) {
    Video video = (Video) item;
    // usar o Video
}
  • 2

    I was refactoring Bruno’s code but then the page was updated and already had the sensational explanation of hkotsubo :D Anyway the solution I was working on is here https://github.com/joellobo/stackoverflow/blob/master/364318/src/com/stackoverflow/Songdriver.java

  • 1

    I thank hkotsubo and Joel lobo, they are professionals who make us enjoy learning to program , you gave perfect explanations, I learned a lot from you, sheltered friends, my dream is to reach the level of knowledge of you and be able to help others ..

  • Friends just one more question, I want to implement a way to increase video time in percentage, EX: If(vizualizacoes < 1000) the time is the same , If If(visualizations > 1000 && vizualizacoes < 10000) increase by 2% the time, duration= time_video *(2/100), my doubt is where implement, I can put of sector controller in the Video class.

  • Okay Thanks for your attention.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.