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?
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;
}