Pergunta

Em Java, suponha que tem 3 classes, C estende-se a partir de B, que se estende a partir de uma.

class X {
   interface A {}
   interface B extends A {}
   interface C extends B {}
   void f(A a) {}

   void test() {
      C c = new C()
      B b = (B) c;

      f(b);
   }
}

Se eu faço algo assim, como mostrado na test() acima:

C c = new C()
B b = (B) c;

f(b);

f() aceita b como tipo C desde C e B ambos se estendem desde A. Eu queria f() para receber b como tipo B e não digite C.

Existe uma maneira de forçar esta upcasting?

Foi útil?

Solução

f() irá sempre receber algo digitado como A (apesar de sob as cobertas É realmente um B ou C, e pode ser abatido de forma apropriada).

Você pode definir um f adicional () assim

f(B b);

e, se necessário

f(C c);

e o correto será chamado, dependendo da classe do argumento. isto é, o compilador determina que a função é chamada, dependendo do tipo do argumento. Isto é diferente de uma expedição dinâmica (ou polimorfismo), que iria ocorrer em tempo de execução.

Note que o seu elenco na questão é redundante. Você pode escrever:

C c = new C()
B b = c;

f(b);

C uma vez que se estende a partir de B, C é um B.

Outras dicas

Você parece estar confuso sobre a diferença entre o tipo de tempo de compilação e tipo de tempo de execução.

Você está criando um objeto (apontou para as referências c e b) do tipo C, e ele irá estadia a C, porque é impossível mudar o tipo de tempo de execução de um objeto e, portanto, o comportamento; lançando você pode simplesmente mudar o seu tipo de tempo de compilação, o que afeta a forma como o compilador trata-lo.

Você pode dar mais algumas informações sobre o problema concreto que você está tentando resolver? O mais provável é que há uma maneira para atingir seu objetivo, alterando o design.

Eu queria f para receber b como tipo B e não digite C.

A C é um B é um A.

Dentro de f, f só vê a parte A de seu a parâmetro Se f chama uma função A pública que é substituído em C, a substituição C é chamado.

Isso é como virtual funções de trabalho. A idéia é, o objeto a que se refere é realmente um C, portanto, deve apresentar um comportamento C. Se você quer um comportamento B, passar uma instância B, não uma instância C.

Se 'C' e "B' deve ter o mesmo comportamento, não ovveride que o comportamento em C.

Por que você quer fazer isso?

A sua pergunta não faz sentido. O que você quer dizer com "f aceita b como tipo C"?

f aceita b como tipo A, desde a assinatura do método diz "A". Se você chamar métodos em b, eles vão ser invocado em C se C substitui-los. Mas este é um comportamento padrão em Java (todos os métodos são como métodos virtuais em C ++), e não há nenhuma maneira de mudar isso.

Talvez você possa descrever o problema real, então poderemos ser capazes de ajudar.

O fato de que você pode passar qualquer subclasse de A como um parâmetro de f (A a) é inerente à OO em Java, não há nenhuma maneira você pode ir em torno deste. Se C estende A, você pode sempre usá-lo onde é esperado um A.

Você pode usar o reflexo para verificar se o parâmetro é de classe A:

public void f(A a) {
  if (a.getClass() == A.class) {
    // ok, go on
  }
  else {
    System.err.println("The parameter is not of class A!");
  }
}

não sei se é isso que você quer, mas pode ser útil.

Seu problema pode ser resolvido através da compreensão da diferença entre o tipo de referência e tipo de instância. Quando você lançar-vos objeto C como um B, você só mudar o tipo de referência - a instância real do objeto ainda é um objeto C - esta deve ser bastante óbvio se você olhar para o objeto no modo de depuração. Alterar o tipo de referência únicos impactos como as alças do compilador / percebe o código - o comportamento de tempo de execução não deve ser afetado. Qualquer chamada de método em um objeto C será sempre invocar o método de C (independentemente de haver ou não o objeto foi fundido a outra coisa). Se você overode um método de B e deseja chamar a versão de B do método, então você vai precisar para criar uma instância B.

O fato de seu código tem uma referência a um A não significa que o objeto que está sendo apontada também é um A. Se for um um C continua a ser um C. A referência na sua fonte apenas limita os métodos disponíveis na sua fonte. Fundição só é necessária porque às vezes é preciso um método em um tipo diferente e precisamos enganar o compilador por isso vamos nós começar a usar métodos sobre as castas de digitar. Naturalmente o elenco pode falhar em tempo de execução se a tentativa de nos inválido.

In upcasting and downcasting the  object first upcast then downcastenter
class A
{
}
class B extends A
{
}
Class M
{
  psvm(String ar[])
{

   A a1= new B();
   B b2=(B)a1;
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top