Is it possible to simulate the C++ 'Friend' keyword in Java?

Asked

Viewed 71 times

-1

Is there any way to simulate this in Java? I would like to have access to a private builder of one class in another, but this other class cannot be nested. This is for the logic of a game where I would have a class Inimigo and another Raca, and I need to make sure Inimigo be instantiated only using Raca, that way I could define in a simple way the Raca of Inimigo.

As in this example:

// Raca
public class Raca {
    private final int dano;
    private int vida;

    public Raca(int vida, final int dano) {
        this.dano = dano;
        this.vida = vida;
    }

    // Chamada de construtor privado
    public Inimigo novoInimigo() { return new Inimigo(this); }

    public int getVida() { return vida; }
    public int getDano() { return dano; }

    // Outros métodos que não nos interessam...
}

// Inimigo
public class Inimigo {
    // Se fosse C++:
    // friend class Raca;

    private int vida;
    private Raca raca;

    private Inimigo(Raca raca) {
        this.raca = raca;
        this.vida = raca.getVida();
    }

    public int getVida() { return raca.getVida(); }
    public int getDano() { return raca.getDano(); }

    // Outros métodos que não nos interessam...
}

I do this so I don’t have to create a different class for each type of Inimigo in the game (many).

  • The most you can do is share methods within the same package. You don’t have that "level" of friendship, only: public / protected / "package" / private. The package-level view scope is obtained by default of the visibility modifier

  • You want to instantiate one class within another only?

  • Yes, it’s for the logic of a game

  • If you can [Edit] the question giving more details of the problem, maybe someone will give another solution. Because there is no such resource in Java (although simulate in a crazy way - but you can’t know if this solves your case, so please edit the question, otherwise all the answers will be guesses...)

  • 2

    Sincerely? Your code for me is clear that you should be a public builder. Why you need to remove builder access from other corners?

  • 1

    Or even use one factory of enemies, to create them on a template. Or a builder

  • That’s what I was going to say. If the builder of Inimigo for public, it already works with the restriction of "being instantiated using only Raca". Just with the code that’s there, there’s no justification for the constructor to be private, and using Reflection to access it is a worse solution than simply changing to public

  • Why Raca has more complex methods to define the behavior of that Raca, and that could bring problems putting this in the Inimigo. This code for behavior involves reference to other parts of the game, for example Render. In addition the builder of Inimigo and Raca Not only do that, but get into what I quoted above extending into other parts of the game. This would make me have to show how these other parts work for the code to be readable, so I chose to give a simple example.

  • 1

    From your description, the impression you get is that classes are doing more than they should. Maybe if you break them into smaller parts (for example, have a class just to define specific behaviors of Inimigo, leave things more uncoupled from the Render, the constructor should only build the object and then, other things not directly related to the creation of that instance should be separated - maybe a Factory that encapsulate this is better, etc), do not need to use Reflection and the code gets better. Anyway, good luck :-)

Show 4 more comments

1 answer

1


From the description of your question it looks like a XY problem, you don’t need to use a complex resource of another language just to instantiate a private constructor class in Java.

Following this line, where you would just like to instantiate a private constructor class elsewhere, follow a few examples considering the following class:

class MinhaClasse {
    private MinhaClasse() {
        // NOP
    }
}

You can access the constructor via Reflection:

Constructor<MinhaClasse> constructor = MinhaClasse.class.getDeclaredConstructor();
constructor.setAccessible(true);
MinhaClasse minhaClasse = constructor.newInstance();

Or you can create a static method to return the instance to you:

class MinhaClasse {
    private MinhaClasse() {
        // NOP
    }

    public static MinhaClasse create() {
        return new MinhaClasse();
    }
}

And use MinhaClasse.create() where necessary.

  • I imagine that reflection is better, because I have no plan to offer the instance of (in this example) MinhaClasse within itself.

Browser other questions tagged

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