2

I have a question about the code below.

When I run the project, marks an error in the calling of ImprimirDatos() method, the errors says:

cannot find symbol. symbol: method ImprimirDatos(). location: class Articulo.

I wrote the method in the subclass deRevista. I don't understand why is asking for the method to be in the base class.

NOTE: If you see something unusual in my code, feel free to 'correct' it, I'm totally new in this subject.

interface ImprDatos
{
    String ImprimirDatos();
}

class Autor
{
    private String nombre;
    private String adscripcion;

    Autor(String nombre,String adscripcion)
    {
        this.nombre=nombre;
        this.adscripcion=adscripcion;
    }

    String getNombre()
    {
        return nombre;
    }

    String getAdscripcion()
    {
        return adscripcion;
    }

    void setNombre(String nombre)
    {
        this.nombre=nombre;
    }

    void setAdscripcion(String adscripcion)
    {
        this.adscripcion=adscripcion;
    }
}

abstract class Articulo 
{
    private String nombre;  
    private Autor autores[]=new Autor[4]; 
    private String fechaPublicacion;
    private int codigo;

    Articulo(String nombreArt,String fechaPublicacion, String nombre,String adscription,String nombre1,String adscripcion1,int codigo)
    {
        this.nombre=nombreArt;
        this.fechaPublicacion=fechaPublicacion;
        autores[0]=new Autor(nombre,adscripcion);
        autores[1]=new Autor(nombre1,adscripcion1);
        autores[2]=new Autor(nombre,adscripcion);
        autores[3]=new Autor(nombre1,adscripcion1);
        this.codigo=codigo;    
    }
    Articulo()
    {
    }

    String getNombre()
    {
        return nombre; //del articulo
    }   
    String getfechaPublicacion()
    {
        return fechaPublicacion;
    }  
    int getCodigo()
    {
        return codigo;
    }
    String getAutores()
    {
        String c=null;
        c=autores[0].getNombre()+" "+autores[0].getAdscripcion()+" 
 "+autores[1].getNombre()+" "+autores[1].getAdscripcion();

        return c;
    }

    void setAutores(Autor[] autores) 
    {
        this.autores = autores;
    } 
    void setNombre(String nomArt)
    {
        nombre=nomArt;
    }
    void setfechaPublicacion(String fechaPublicacion)
    {
        this.fechaPublicacion=fechaPublicacion; 
    }
    void setcodigo(int cod)
    {
        codigo=cod;
    }    
}

class deRevista extends Articulo implements ImprDatos
{
    private String nomRevista; 
    private int añoEdicion; 
    deRevista(){}
    deRevista(String nombreArt,String fechaPublicacion, String 
    nombre,String adscripcion,String nombre1,String adscripcion1,String 
    nomRevista,int añoEdicion,int codigo)
    {
        super(nombreArt,fechaPublicacion,nombre,adscripcion,nombre1,adscripcion1,
 codigo);

        this.añoEdicion=añoEdicion;
        this.nomRevista=nomRevista;    
     }


     void setañoEdicion(int nom)
     {
         añoEdicion=nom;
     }
     int getañoEdicion()
     {
         return añoEdicion;
     }

     void setnomRevista(String nom)
     {
         nomRevista=nom;
     }
     String getnomRevista()
     {
         return nomRevista;
     }

     public String ImprimirDatos()
     { 
         return " Nombre del articulo: " + getNombre() + " Nombre de la 
  revista: " + getnomRevista() 
        + " Año de edicion: " + getañoEdicion() + " Autores: " +
           getAutores() + " Codigo: " + getCodigo() + " Fecha de 
  publicacion: "
        + getfechaPublicacion();
     }
 }  

class deCongreso extends Articulo implements ImprDatos
{
    private String nomCongreso;

    deCongreso(){}   
    deCongreso(String nombreArt,String fechaPublicacion, String 
nombre,String adscripcion
        ,String nombre1,String adscripcion1,String nomCongreso,int 
codigo)
   {
        super(nombreArt,fechaPublicacion,nombre,adscripcion,nombre1,adscripcion1,codigo);
        this.nomCongreso=nomCongreso;

    }
    void setnomCongreso(String nom)
    {
        nomCongreso=nom;
    }
    String getnomCongreso()
    {
        return nomCongreso;
    }

    public String ImprimirDatos() 
    { 
        return "Nombre del articulo: " + getNombre() + " Nombre de la 
 revista: " + getnomCongreso()
        + " Autores: "+getAutores() + " Codigo: " + getCodigo() + " 
 Fecha de publicacion: "
        + getfechaPublicacion();  
    }    
}

public class Articulo17ago
{  
    public static void main(String[] args) 
    {  
        Scanner x=new Scanner(System.in);

        String  au1[]=new String[4];
        String ads1[]=new String[4];

        Articulo y[]=new Articulo[4]; 

        //ARTICULO DE REVISTA:
        for(int i=0;i<2;i++)
        {
            System.out.println("Introduzca el nombre del articulo");
            String art=x.nextLine();

            System.out.println("Introduzca el nombre de la revista");
            String rev=x.nextLine();

            System.out.println("Introduzca el año de edicion");
            int año=x.nextInt();

            System.out.println("Introduzca el codigo ISSN");
            int cod=x.nextInt();

            System.out.println("Introduzca la fecha de publicacion");
            x.nextLine();   
            String fec=x.nextLine();
            for(int k=0;k<2;k++)
            {
                System.out.println("Introduzca el nombre del autor");
                au1[k]=x.nextLine();
                System.out.println("Introduzca la adscripcion del autor");
                ads1[k]=x.nextLine(); 
            }

            y[i]=new deRevista(art,fec,au1[0],ads1[0],au1[1],ads1[1],rev,año,cod);
        }

        for(int i=0;i<2;i++)
            System.out.println("Datos: "+y[i].ImprimirDatos());


        //ARTICULO DE CONGRESO:
        for(int i=2;i<4;i++)
        {
            System.out.println("Introduzca el nombre del articulo");
            String art=x.nextLine();

            System.out.println("Introduzca el nombre del congreso");
            String rev=x.nextLine();

            System.out.println("Introduzca el codigo ISBN");
            int cod=x.nextInt();

            System.out.println("Introduzca la fecha de publicacion");   
            x.nextLine();
            String fec=x.nextLine();

            for(int k=2;k<4;k++)
            {
                System.out.println("Introduzca el nombre del autor");
                au1[k]=x.nextLine();
                System.out.println("Introduzca la adscripcion del autor");
                ads1[k]=x.nextLine(); 
            }

            y[i]=new deCongreso(art,fec,au1[2],ads1[2],au1[3],ads1[3],rev,cod);
        }

        for(int i=2;i<4;i++)
            System.out.println("DATOS: " + y[i].ImprimirDatos());

    }    
}
Frakcool
  • 10,915
  • 9
  • 50
  • 89
I likeThatMeow
  • 198
  • 1
  • 12
  • 2
    The compiler doesn't know if a particular `Articulo` happens to implement `ImprDatos`. You can only call a method on a type that declares that method, or a subtype thereof. – shmosel Aug 21 '17 at 20:24
  • But I used polymorphism in the vector y[], so in particular y[0] is now an object of the subclass deRevista therefore it can freely use the methods in that class deRevista(). Doesn't work like that @shmosel ? – I likeThatMeow Aug 21 '17 at 20:32
  • 2
    Not at all. If the array were of type `ImprDatos`, polymorphism would allow you to call the method without knowing the concrete type. But without declaring the concrete type or the interface, the compiler can't know the method exists. – shmosel Aug 21 '17 at 20:34
  • That's called [`programming to interface` what you need is `programming to implementation`](https://stackoverflow.com/questions/383947/what-does-it-mean-to-program-to-an-interface). And [read this to get clear idea](https://stackoverflow.com/questions/2697783/what-does-program-to-interfaces-not-implementations-mean) – Blasanka Aug 21 '17 at 20:37
  • Side note, read about [Java Naming Conventions](http://www.oracle.com/technetwork/java/codeconventions-135099.html) You seems to be using .Net Naming Convention – Jorge Campos Aug 21 '17 at 20:55

2 Answers2

2

Change

Articulo y[]=new Articulo[4];

to

ImprDatos y[]=new ImprDatos[4];

An Articulo[] array may contain anything that extends Articulo. Since Articulo doesn't implement ImprDatos, there's no guarantee that all subclasses will implement it, so the compiler won't let you assume that objects in that array have the ImprimirDatos method. To tell the compiler that the array objects must implement ImprDatos, you can simply declare it as an ImprDatos[] array instead.

Alternatively, if it makes sense that all Articulo objects should implement ImprDatos, you can just change the class declaration to abstract class Articulo implements ImprDatos and no other changes are necessary.

Sean Van Gorder
  • 3,393
  • 26
  • 26
1

As has been said in the comments above, your interface ImprDatos knows about its method ImprimirDatos() (which according to the Java naming conventions should be named imprimirDatos() (first word lower case)).

Your Articulo class knows nothing about it.

We then need to know the following:

There are 2 states when you create your code:

  1. The compilation time
  2. The running time

At compilation time, y array knows it is of type Articulo (which knows nothing about ImprimirDatos() but at run time it behaves as an deRevista or deCongreso types (which know about the ImprimirDatos() method).

So, what we can do in order to "force" the compiler to compile our code, are 2 things:

  1. Explicitly casting y array to ImprDatos interface...

    You could change this line:

    System.out.println("Datos: "+y[i].ImprimirDatos());
    

    To this one:

    System.out.println("Datos: " + ((ImprDatos) y[i]).ImprimirDatos());
    

    This tells the compiler the following:

    • "Hey compiler! I have this element of this array of type Articulo but I want you to treat it as an ImprDatos type element", the compiler will say:

    • "OK, I'm telling you that's not secure, but if you still want to do it, then it's your fault if something breaks"

    Then you will be able to compile your code, however it could break while running it.

  2. Change your y array type to the interface type:

    So, changing:

    Articulo y[] = new Articulo[4];
    

    To:

    ImprDatos y[] = new ImprDatos[4];
    

might do the work too.


Side note (irrelevant to the question): As your code is written in Spanish (and I checked your profile and you're from Mexico (like me)), maybe you could feel more comfortable writing in Spanish at Stack Overflow en Español (however I feel more comfortable here since I learn a little bit more (technical) English and can practice it too), I'm just letting you choose whether you want to stay and write your questions and read answers in English or Spanish (or both!)

I think you're being confused on how interfaces and abstract classes work... I could try to explain it later if you want (not through Stack Overflow since it could be really long post and too broad, but through other media).

Frakcool
  • 10,915
  • 9
  • 50
  • 89