Interface or Abstract?

Asked

Viewed 2,035 times

10

I read several contents on this subject, until arriving at this example:

public interface Funcionario{  
      public void trabalha();  
      public void recebe(double salario);  
}


public abstract class Geek implements Funcionario{  
    public abstract void trabalha();  
    public abstract void recebe(double salario);  
    public void programa(){  
       System.out.println("import java.io.*; :) ");  
    }  
}  

public abstract class BusinessMan implements Funcionario{  
     public void trabalha(){  
         System.out.println("$$$");  
     }  
     public abstract void recebe(double salario);  
}


// programador é um geek e também um funcionário...  
public class Programador extends Geek{  
      private double salario;  
      public void trabalha(){  
           super.programa();  
      }  
      public void recebe(double salario){  
            this.salario = salario;  
      }  
}

/* analista também é um geek e um funcionário, mas que trabalha de maneira diferente ao programador*/  
public class Analista extends Geek{  
      private double salario;  
      public void trabalha(){  
           super.programa();  
           supervisionaProjeto();  
      }  
      public void recebe(double salario){  
            this.salario = salario;  
      }  
      private void supervisionaProjeto(){  
           System.out.println("Supervisiona");  
      }  
}  

public class Gerente extends BusinessMan{  
     private double salario;  
     private final double BONUS = 1000.0d;  
     public void recebe(double salario){  
         this.salario = salario + this.BONUS;  
     }  
}


public class Empresa{  
   public static void main(String[] args){  
      private Funcionario[] funcionario = new Funcionario[5];  
      funcionario[0] = new Programador();  
      funcionario[1] = new Programador();  
      funcionario[2] = new Analista();  
      funcionario[3] = new Programador();  
      funcionario[4] = new Gerente();  
      // faz alguma coisa...  
   }  
}

Source: http://www.guj.com.br/java/6854-classe-abstrata#38794

I changed the interface Funcionario by one abastrata class, and I made the other classes, which I used to implement, now extend it. So:

public abstract class Funcionario {
    public abstract void trabalha();
    public abstract void recebe(double salario);
}

public abstract class Geek extends Funcionario{
    @Override
    public abstract void trabalha();

    @Override
    public abstract void recebe(double salario);

    public void programa() {
        System.out.println("import java.io.*; :) ");
    }
}

public abstract class BusinesMan extends Funcionario {

    @Override
    public void trabalha() {
        System.out.println("$$$");
    }

    @Override
    public abstract void recebe(double salario);

}

There was no modification when compiling and running.

My question is: In this specific case changes anything with these changes? Is there any functionality that I will lose or gain?

Note: I am not referring to performance. I am referring to the issue of maintenance or complexity, for example, if later I need to add some more type of employee, there will be difference in the two cases?

  • 1

    It would be a duplicate of http://answall.com/questions/3603/classe-abstraction-x-interface, although the language is not the same?

  • Language really won’t be the differential. Both follow very similar characteristics and the response of one would serve the other language in this case. What can differentiate one from the other is that here is a concrete case to be analyzed. Certainly the C# complements this. If you’re a duplicate, I’d like another opinion.

  • 1

    I read that question and was very much in doubt in asking my question, but I could not get the answer in it for my case. So I asked a new question. Anyway the two address the same theme... Any suggestions so I can edit the question and be more different from the other?

  • 1

    @Earendul would probably cause more problems because then it could invalidate the answers. What you just said is fundamental to help in the decision. I finished reading the other and really think that here asks and out given something different.

  • @Earendul From what you say we can not consider duplicate even. I’ll keep our comments here, as a reference, in case anyone in the future thinks they’re duplicate.

3 answers

8


At first there was not much change. Interfaces are usually preferred when there are no status or implementations, which is your case. And this is the most important thing to note. That case does not demand classes. If the problem were another I would think differently. This is why it is important to never go after good practices and analyze the specific problem. Understand what you want. For this it is important to understand the difference between the two.

You could even have a future limitation using an abstract class because Java only allows "real" inheritance from just one class. And any class that inherits from the abstract class Funcionario cannot inherit from another class, can only implement other interfaces.

In practice I doubt that this really is a problem in most cases. If you just implement Funcionario in the described classes will allow in the future that you can inherit from some class (abstract or not) since you had only implemented interfaces and no class. But will you modify these existing classes to inherit from another class? It will hurt the Open/Close principle? And it’s usually important in these cases. I’m not saying there’s no situation where this might be interesting, but in general it’s not.

Is there any reason to prefer the abstract class? If you don’t find one, I’d stick to the interface. In general the reason is that you need status. Even if you need implementations, I don’t know if it would be justified, especially in Java 8 with the default methods. Unless you need to implement "implementation details", i.e., private methods.

The way that Funcionario is described to me seems to be stating some characteristics that an element that is an employee of some kind should have. Which is different from saying Funcionario contains important definitions for all employees. It is the famous difference of was and had. Use classes when derived classes will be that, in this case, sane employees. Or use interfaces when derived class only have those characteristics, defined behaviors (but not implemented).

By name it may be tempting to think Geek or Analista sane employees and not only possess characteristics of an employee. But the code shows something different. That’s why the right specification is important to make the right choice. Maybe you know something we don’t know.

About this you can learn more about the principle of Liskov’s substitution (in English, as always, is better) (has answer here).

Remember that in theory it is easier to transform an interface into an abstract class if one day this is necessary than the other. In fact, they’re both gonna be hard work and take risks.

Really performance and other technical issues are little important near the engineering problem you will have. In general it is easier to add interfaces. You could have advantages in the abstract class if you want implement or modify existing implementations in it and that this is automatically reflected in the descending classes. But this needs to be done so carefully that one must always question whether it’s worth it.

  • 2

    Very good. It reminded me of the teacher’s phrase: "Use inheritance when the object is a special kind of, and not a role assumed by". I’ll take your advice "never go after good practices and analyze the specific problem".

  • 1

    I don’t demonize good practice, I demonize what people do with it. They make it immutable rules, universal truths. That’s where they don’t help.

  • And I think this generates a lot of distrust and insecurities as well. We always end up thinking "will I be doing it right?".

  • And there is not much to do except study, ask, practice, try to improve, finally, get experience. Ah, and to err too, because it is a mistake that one learns. With 30 years of experience I live erring.

7

Conceptually there is no difference between a interface and a purely abstract class, that is, with all abstract methods.

With respect to changes, the abstract class would implement a non-extabstracted method to be reused in the subclasses.

In short, abstract classes help if you have a generic type (superclass) that is the basis for more specific and specialized types (subclasses).

Interfaces are better at specifying the behavior of a type. Don’t think about interfaces for code reuse.

In fact, also be careful when using inheritance to reuse code. The price to be paid (high coupling between super and subclasses) can be very expensive. Whenever you can, give preference to the delegation.

Mixed approach

You can also use abstract interfaces and classes together.

Example:

public interface Funcionario {  
      void trabalha();  
      void recebe(double salario);  
}

public abstract class FuncionarioAbstrato implements Funcionario {
    double salario;
    public abstract void recebe(double salario) {
        this.salario += salario;
    }
}

I consider this approach to be more flexible, because in the event of another type of employee that does not fit into your class hierarchy, just implement the interface in a completely new implementation.

Segregation of Interfaces

Another approach that may be useful in the long term is to segregate interfaces so that actions are more specific.

Imagine that the system also counts the owner on the staff, for whatever reason. However, the owner does not work, he just receives.

So you could have a model like this:

public interface Trabalhador {  
      void trabalha();  
}

public interface Recebedor {  
      void recebe(double salario);  
}

public abstract class RecebedorAbstrato implements Recebedor {
    double salario;
    public void recebe(double salario) {
        this.salario += salario;
    }
}

public class Programador extends RecebedorAbstrato implements Trabalhador {
    public void trabalha() {  
        System.out.println("import java.io.*; :) ");  
    }  
}

public class Dono extends RecebedorAbstrato {
    //nada além d ereceber
}

And if the analyst’s difference is simply to do something else, he could do so:

public class Analista extends Programador {
    public void trabalha() {  
        super.trabalha();
        System.out.println("Supervisiona");    
    }  
}

Well, it was just a few ideas. There is not necessarily a more correct modeling, it always depends on the problem.


Note: Method signatures on interfaces do not need the public, because the methods are always public

  • 1

    Perfect. I clarified a lot the ideas. Very interesting your examples, I’ll even save the link to queries in the future. Thanks.

4

Well abstract classes and interfaces are different things and intended for different uses.

The main difference is that in an abstract class you can have a mix of abstract methods that someone will have to implement to consume the already implemented class and methods. In an interface you only have method declaration.

In my understanding abstract classes should be used exactly when it is interesting to share an implementation with things to be implemented already interfaces should be used when we only want to define a communication pattern between calls.

To learn more take a look at this link. (English)

http://www.programmerinterview.com/index.php/java-questions/interface-vs-abstract-class/

Browser other questions tagged

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