What does an abstract class type variable mean?

Asked

Viewed 1,128 times

4

Studying Pattern design I saw something that I didn’t understand very well what it means, when we have a variable of the type of an abstract class what it means exactly?

Example:

ClasseAbstrata variavel;

Which means when we have this type and match the new variable to another class?

Example of the code I have here which compiles but I do not understand it very well:

FabricaAbstrata fabricaCor = ReprodutorFabrica.getFabrica("COR");
  • This abstract factory has the method getCor().

  • The method getFabrica() of ReprodutorFabrica returns a creator of an object type, in which case returns the color creator.

  • 3

    I guess that answers: An interface is a variable?

  • Did any of the answers below solve your problem? Do you think you can accept one of them? Check out the [tour] how to do this, if you still don’t know how to do it. This helps the community by identifying the best solution for you. You can only accept one of them, but you can vote for any question or answer you find useful on the entire site.

2 answers

6

I almost closed as a duplicate of this: An interface is a variable?. It’s essentially the same thing.

ReprodutorFabrica does not return something because it is a class, classes do not return. Who returns is the getFabrica(). This returns an object that is from a concrete class derived from FabricaAbstrata. Note that I don’t even know what this method returns, but that can only be it.

What matters there is the concrete object, the variable being of a type means that it can store any object that is of this type, including its derivatives. But the variable cannot have a concrete object that is exactly an abstract type, these are incomplete types and cannot be instantiated. It’s all about the contract.

We can only assign an object of a class that conforms to the type of the variable, ie it has to be of the same type or has inherited or implemented the type of the variable.

In that case we can say that the abstract class is functioning as interface. That’s what it’s called program to the interface and not to the implementation.

3

A basic concept in object orientation is inheritance. Good parts of the project patterns are implemented based on these concepts, where one class is the basis for implementing other classes or even ensures that a set of instances have a common point that can be used in various contexts, this common point is usually what we call the signature or contract and most of the time is the base class.

A trivial example:

class Carro
{
   private int nivelCombustivel;
   void SubirNivel(int valor)
   {
       this.nivelCombustivel += valor; 
   }
}

A class that inherits from the basic class Car:

class Gol extends Carro
{
  private string nitro;
  private int motor=1;     
}

In general, it’s quite easy and common to do this kind of thing, a place where I have a more basic class that complements the previous one by adding a behavior. Another even more important factor is that by possessing the same signature base, everywhere I can use the car class, I can also use instances of the Gol class.

However, imagine now that you start to have many types of car and that you need to retouch the appropriate type of car according to a parameter provided by the user, let’s assume that it is the engine and that only the Beetle has a 2.0 engine :)

class Fusca extends Carro
{
  private string nitro;
  private motor = 2;

}

So in the code, every time the car was requested you would probably have an if:

if(tipoMotor == 2)
   return new Fusca();

And I would go out repeating this snippet of code in various places where this logic of selection was needed, this is an indicator that you’re in need of a pattern, so let’s go to the car factory. :)

Opa, every time I return the type of car, the user will inform the type of engine and I will perform some logic to return a suitable car instance. Well, there are some problems there:

1) The type of class I must instantiate will depend on the type of parameter provided by the user and this cannot be fixed in the code. 2) The code snippet that selects the class type will have to be used everywhere that will instantiate cars. 3) The number of cars can grow and I will need to change all the places that use this logic to assemble a car instance.

Well, this case is for a factory or factory, as you’ve been researching. In this case, a factory is basically an object that is responsible for keeping the logic of constructing other objects when this logic is complex, in our case, the method that will return the car.

And we’re lucky, as all cars inherit from a basic car class, we can’t use it as a return from our factory, something like that:

class FabricaCarros{
   public static Carro GetCarro(int motor)
   {
      if(motor == 2)
       return new Fusca();
      else return new Gol();
   }
}

Notice that I can call the Getcarro metodo where I want and it will provide me with the appropriate type of car. External classes do not need to know the implementation of the VW class or gol class because they both inherit from Carro.

For example, if I have a Postogasolina class that instantiates a new car and fuel the car with +2 of fuel, then I would have something like:

class Postogasolina{ Public Car Getcarroabastecido(int motor) { Car car = Manufacture cars.Getcar(motor); car.Raising level(2); re-turn; } }

Note that the factory service consuming class does not know the implementation of the car it is fueling, so you can include as many rules as you want in the factory method, for as many models as you want and the system will continue fueling.

But, let’s make things even more complicated :D Now, your car classes are part of a framework for creating racing games and you will sell your components around. So let’s go to some trouble:

1) Face it, the Car Class, being a normal class, can be instantiated at any time by anyone who picks up your framework, however, the car class does nothing!! she doesn’t even have a motor!! the rules are in the factory and the programmers(users) shouldn’t instantiate cars without inheriting from the basic class :(

2) As the rules for the type of car always depend on the engine, you want to force everyone to create new classes for new types of cars.

3) However, you still need a part of the code (Subirnivel) to fuel your car independent of the model and want it in the car class and as its rank class is very beautiful because the code does not need to know the implementation of the classes that inherit from the car class, you want to keep it that way without changing the rest of the code, so you just need to force the new car implementations to have the same signature and behavior.

Well, you can think of an interface, however, interfaces are used when you want to force a concrete implementation to maintain a signature, but, does not allow code in the base.

So I couldn’t use my Rise Level method in car :(

It is in this type of scenario that you use an abstract class:

abstract class Carro
{
   private int nivelCombustivel;
   void SubirNivel(int valor)
   {
       this.nivelCombustivel += valor; 
   }
}

Basically, I put the car class as abstract. It has several consequences, but first of all, remember that I still inherit her other classes.

When you create an abstract class you do the following:

1) You may not instantiate the class (e.g.: no new car())

2) If you cannot instantiate, you have to always inherit to another class and implement the necessary there and then yes you instance (ie, you can only instantiate classes that inherit from the abstract class (eg.: goal). We say that the classes that implement inheritance are the concrete implementations of the abstract class.

Like a car is anything, but a goal is a goal. :)

3) In an interface you only specify the signature/contract, in an abstract class, you can have a code snippet that will be taken to the concrete implementations (so I can continue using Subirnivel).

So, following the two standards I explained to you, what you probably have is a factory that builds a factory.

**In the above examples, I have only one Fabrica level because my default returns already the concrete implementation of the car class. In your case, you probably have more than one factory type to generate the color object construction.

Hence, its first level returns the concrete implementation of the color object manufactures which in turn returns the concrete implementation of Color.**

You are probably applying the same pattern because there is complexity even in the creation of Manufactures color object.

FabricaAbstrata fabricaCor = ReprodutorFabrica.getFabrica("COR"); // retorna a implementação concreta uma fabrica da classe cor.

Cor c = fabricarCor.GetCor() // usa a fabrica retornada para retornar a implementação concreta da Cor.

You can have this because it supports different color schemes and the color factory needs to return the correct color types for each type of support (vga, xvga, svga, etc...). Then use the correct factory to return the color. It’s like recursively applying the Factory :) pattern if this exists :D

Browser other questions tagged

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