Instanciar uma classe nos atributos de outra classe é uma boa prática?

Boa noite.

Tenho várias classes que precisam acessas os atributos de outra classe específica. Instanciei esta classe no Start() em todas as outras classes, mas estava dando erro de nullReference… daí instanciei essa classe nos atributos das outras classes e funcionou. Fiz assim msm ó:

NomesUsados nomesUsados = new NomesUsados();” <<< esta linha nos atributos das outras classes, ou seja:

public class Abertura : MonoBehaviour {

      // Atributos
      NomesUsados nomesUsados = new NomesUsados ();

     // Métodos abaixo
}

Já pesquisei e nos resultados vi que pode, mas não sei se é uma boa prática. Se não for uma boa prática, qual seria a melhor? Pois já testei em vez desta instância, colocar a linha:

{get; set;}” <<< e não funcionou.

Alguém? Desde já mt obg!

Não lembro de ter visto essa prática sendo listada como má.

1 curtida

Cada vez que instancias uma classe estás a criar uma instância da classe e não a aceder a uma que criaste noutro lado.
Não é uma má prática iniciar onde é preciso, antes pelo contrário, mas o que estás a fazer não vai resolver o teu problema. A tua classe deve ser inicializada num sítio e passada como parâmetro para as restantes classes que dela necessitem.

1 curtida

Bom dia! Mt obg pela ajuda!

1 curtida

Bom dia!

Eu não entendi mt bem as suas palavras, mas olha, resolveu viu!

O que vc quis dizer aqui: “A tua classe deve ser inicializada num sítio e passada como parâmetro para as restantes classes que dela necessitem.”?

Cada vez que fazes isto
NomesUsados nomesUsados = new NomesUsados ();
estás a criar uma instancia nova, não estás a aceder aos mesmos valores de outra instância já criada.

Assim, se na classe A tiveres este new e na class B também, ao fazer em A
nomesUsados.setXxxx(1);
não vai fazer com que isto, em B, tenha o valor 1:
nomesUsados.getXxxx();

Para isso funcionar, tens de criar a instancia só uma vez e passar como parametro no construtor da outra. Algo assim:

class A {
     private NomesUsados nomesUsados = new NomesUsados ();
     private B = new B(nomesUsados);
(...)
}

class B {
   private NomesUsados nomesUsados;

   public B(NomesUsados nomes) {
        nomesUsados = nomes;
   }
1 curtida

O que ele quis dizer é que a cada new é uma nova instância, ou seja, imagine esse cenário:

Carro carro1 = new Carro();
carro1.setCor("Azul");

Carro carro2 = new Carro();
carro2.getCor();

O primeiro carro setou a cor para Azul, não quer dizer que o segundo terá essa cor Azul tbm, pois são instâncias diferentes, mesmo referenciando o mesmo objeto (Classe).

Se precisa que seja compartilhada essa informação entre todas as classes, deverá fazer de outra maneira.

EM TEMPO:
A não ser que crie variáveis estáticas.

1 curtida

Então. Eu sei disso sobre as Instâncias, a questão não foi essa. O que aconteceu foi que eu criei uma Variável Global do tipo “NomesUsados” nos Atributos das outras classes e Instanciei esses Atributos nos Métodos “Awake()” dessas classes, justamente para que cada classe tenha uma Instância de “NomesUsados” em sí. Por exemplo:

class ClasseA: MonoBehaviour {

       // Atributos
       NomesUsados nomesUsados;
  
      // Método que roda o 1º Frame na Unity
      void Awake() {
  
      // Instância da Classe **NomesUsados**
      nomesUsados = new NomesUsados();
  }
}

Outra Classe:

class ClasseB: MonoBehaviour {

       // Atributos
       NomesUsados nomesUsados;
  
      // Método que roda o 1º Frame na Unity
      void Awake() {
  
      // Instância da Classe **NomesUsados**
      nomesUsados = new NomesUsados();
  }
}

O mesmo para as classes ClasseC, ClasseD, ClasseE… enfim. Cada uma tem uma Instância de “NomesUsados”. Até aí tudo bem.

Também fiz assim na Classe que guarda os Dados, o nome dela é “Jogador”. Essa classe não tem a classe base “MonoBehaviour”, consequentemente não tem “void Awake()”. O que ela tem é o seu Construtor Jogador().

Daí fiz na classe “Jogador” igual às demais classes, declarei “NomesUsados” nos Atributos e Instanciei “NomesUsados” no Construtor, mas não funcionou! Deu o erro “NullReferenceException”.

Então tirei a Instância do “Construtor” e coloquei nos “Atributos”, ficou assim:

class Jogador {

       // Atributos
       NomesUsados nomesUsados = new NomesUsados();
  
       // Construtor
       public Jogador(){}

       // Métodos abaixo...
  }
}

Funcionou. Mas fiquei com dúvidas, então criei este tópico. As dúvidas:
Será que Instanciar nos Atributos é uma boa prática?”. “Se sim, será que isso pode gerar algum erro?”, “Se sim, quais?”…

Bom, a resposta que tive é que não é uma má prática. Mas fico com receio de que possa haver algum erro ou erros em algum momento :grimacing:

Daí o @pmlm falou “A tua classe deve ser inicializada num sítio e passada como parâmetro para as restantes classes que dela necessitem. ” e eu fiquei sem entender oq que quis dizer :expressionless:

Mas tá tranquilo. O @edpickler respondeu de forma clara.

Oq vcs dois, @pmlm e @d3z4013, acham sobre essa prática? Já fizeram? Se sim, tiveram algum erro? Se sim, qual ou quais? concordam com o @edpickler ou tem alguma objeção?

Deveria ter funcionado instanciando no construtor também. Observe que você tem que usar o objeto só depois de criá-lo senão dá esse erro que mencionastes.

Como você está aprendendo, veja como usar depuradores (o debug), que lhe vai ser muito útil nessa jornada. Então, marque algumas linhas e com o depurador execute de novo para entender como o fluxo de dados funciona.

ps: parabéns pela escrita e formatação. Se todo mundo fosse assim esse fórum seria muito melhor.

2 curtidas

Nunca vi nada em relação a isso, se precisa instanciar, sem problema nenhum.

Acredito que entendi o ponto dele, que vc queria referenciar uma classe que tivesse suas configurações compartilhadas, o que não seria possível dessa forma, como expliquei anteriormente.

Vc esta começando e vai aprender novas técnicas, melhores formas de se fazer, principalmente estudando sobre arquitetura, mas saiba que criar objetos em diversos lugares do código, não é uma das melhores idéias, mas pode ser que se encaixe no seu projeto.

Acredito que esteja indo bem, continue e vá se aprofundando nos mais diversos temas sobre arquitetura, design patterns, eles te ajudarão a abrir um leque de opções.

2 curtidas

@d3z4013 , vi tua resposta, mas não vi a de @edpickler ! Então. Gente não estou começando agora, já tenho um tempo de programação. Minha pergunta foi sobre uma coisa trivial, porque eu nunca tive essa prática de instanciar nos atributos de outra classe, só isso. O correto é como @edpickler falou, Instanciar no Construtor e que deveria funcionar! Pois bem, eu tava instanciando no Construtor sim, mas não estava funcionando, vou explicar o porquê:

Estou com um Projeto na Unity, não sei se vcs a conhecem. É uma Engine em que vc pode criar Jogos. Existe um Método nativo da Unity que é executado no 1º Frame quando o Jogo é rodado. Trata-se do Awake(). Quando vc dá um “FindObjectOfType” nesse Método, ele dá o erro “NullReferenceException: Object reference not set to an instance of an object”. Então fui pro 2º Método que também roda o 1º Frame, é o Start(). A diferença do Awake() para o Start() é que o Awake() é rodado Antes do Start(), prioridades da Unity, pois bem.

Instanciei o meu objeto “NomesUsados” no Awake(), e deu esse erro. Daí instanciei no Start(), deu mesmo erro. Eu disse “Pronto. Eu gosto assim, amostradinho kkk”. Fui debugar o código. E vi que o método que eu estava usando a instância de “NomesUsados” estava sendo chamado ANTES da Própria instância no Awake() e no Start().

Trocando em miúdos, quando vc dá uma Build no Jogo, a Unity pega todos os Awake()'s que há no seu projeto junta tudo num só Awake() e o executa, um comando após o outro na ordem estabelecida pela Unity, o mesmo para o Start(). Daí, segundo esse fluxo, o que ocorreu foi que o meu bendito método estava sendo chamado ANTES da Instância lá no Awake() e no Start()! Por isso o erro “NullReferenceException”.

Se algum de vcs já trabalhou com a Unity, sabe do que estou falando. Caso tenham a pretenção de trabalhar com ela, já vá ciente de que erros desse tipo acontecem e mt! O problema não foi falta de conhecimento, principalmente do trivial, foram as prioridades dos métodos primitivos da própria Unity. Mas já resolvi! Mt obg pela atenção de Todos!

2 curtidas

Olá boa noite, pra ser sincero nunca vi algo ou alguém dizendo que isso seja má prática, contudo pelo que entendi caso seja algo persistente em seus projetos acredito que pode tronar-se um grande problema pois pode causa um forte acoplamento entre suas classes, o que é listado sim como uma má prática.

1 curtida

@Delmiro, boa noite.

Só sua resposta hj, mt obg por ela! Sim, é isso mesmo que vc falou. Consegui resolver o problema sem essa preocupação! Mais uma vez obg!

1 curtida