java 中抽象类的继承_了解Java中的继承和抽象类

好吧所以我通过谷歌搜索文档,但是我没有找到任何真正描述我想要回答的内容,所以我在这里问你们。

所以我得到了继承,以及它是如何工作的。我遇到问题的有时候我看到一个对象最初定义为一种类型,并设置为不同的类型,我不明白究竟发生了什么。这是一个例子:

说我有一个类动物,并且类猫和狗延伸动物。猫,动物和狗都有一种方法说(),对于猫打印"喵"和狗打印"woof"和动物"不能说话"。

好吧,所以最后这是我的问题。如果制作一只猫(c)然后运行Animal a = c,究竟会发生什么?如果我运行a.speak()会发生什么?哪种说法叫做?当我改变类型时到底发生了什么?我有没有真正的理由使用它?

就抽象方法而言,我的问题是拥有它们究竟是什么意思?在示例中,我已经看到它们已被放入超类中,其下的类定义了确切的行为。通过在超类中放置一个抽象方法,需要它下面的所有类来实现它吗?

感谢你的帮助!

What exactly happens if a make a cat

(c) and then run Animal a = c;? What

happens if I run a.speak();? Which

speak method is called? What exactly

has happened when I change types like

that? Will I ever have any real reason

to use this?

始终是真实类的方法,例如在这种情况下,cat的speak()方法。

As far as abstract methods go, my

question is what exactly is the point

of having them?

例如,他们确保每只动物都有一种方法walk(),你可以召唤每只动物。这是一个保证,说"每个Animal对象都有这种方法,你不必关心它"。

In the examples I've

seen they've been put in super classes

and the classes under them define the

exact behavior. By putting an abstract

method in a super class is one

requiring all the classes under it to

implement it?

实现它或者是抽象的,是的。

Cat c = new Cat();

动物a = c;

a.speak()将打印喵喵。

请检查java多态性。

关于抽象类:

When an abstract class is subclassed,

the subclass usually provides

implementations for all of the

abstract methods in its parent class.

However, if it does not, the subclass

must also be declared abstract.

JLS第5.2节解释了为什么Cat可分配给Animal。 (注意,Animal不能隐式赋值给Cat,因为Cat是"更具体"的类型; Cat是Animal的子类型而Animal是Cat的超类型)

Assignment of a value of compile-time reference type S (source) to a variable of compile-time reference type T (target) is checked as follows:

If S is a class type:

If T is a class type, then S must either be the same class as T, or S must be a subclass of T, or a compile-time error occurs.

If T is an interface type, then S must implement interface T, or a compile-time error occurs.

If T is an array type, then a compile-time error occurs.

If S is an interface type:

If T is a class type, then T must be Object, or a compile-time error occurs.

If T is an interface type, then T must be either the same interface as S or a superinterface of S, or a compile-time error occurs.

If T is an array type, then a compile-time error occurs.

If S is an array type SC[], that is, an array of components of type SC:

[omitted for brevity]

子类型多态性解释a.speak(),但它没有解释为什么Cat可以隐式赋值给Animal。更多细节(JLS链接非常好),这将是一个很好的答案。

第5.2节包含可分配的要求。 java.sun.com/docs/books/jls/second_edition/html/。搜索"将编译时引用类型S(源)的值赋值给编译时引用类型T(目标)的变量,如下所示"。

Cat可隐式赋值给Animal,因为Cat扩展Animal。通常,如果A扩展B,则可以将A分配给B。如果A实现接口C,则可以将其分配给C。这些关系是可传递的,因此如果X扩展Y,而Y又扩展Z,则可以将X的实例分配给声明为X,Y或Z中的任何一个的变量。

Say I have a class animal, and classes cat and dog which extend animal. Cat, animal and dog all have a method speak() which for cat prints"meow" and for dog prints"woof" and for animal"can't speak".

Alright so finally here's my question. What exactly happens if a make a cat (c) and then run Animal a = c;? What happens if I run a.speak();? Which speak() method is called? What exactly has happened when I change types like that? Will I ever have any real reason to use this?

Java中的对象确切地知道它们被创建的类型;它实际上是一个隐藏字段(可以使用Object.getClass()方法检索)。此外,所有非静态方法解析都从最具体的类的方法定义开始,然后向最通用的类??(Object)进行;因为在Java中只有单一的实现继承,所以这是一个简单的搜索。 Cat知道它是Animal的子类型,它是Object的子类型,而c知道它是Cat,与变量的类型无关。

执行赋值时,编译器会检查所分配的值的已知类型是指定的类型还是其子类型之一。如果是,则分配有效。如果不是,你需要一个显式的强制转换(在运行时进行正确的类型检查;强制转换不能破坏Java的类型系统,它们只会让它变丑)。它不会改变方法查找仍然是动态完成的事实,并且对象仍然知道它实际是什么类型;所有程序正在做的是忽略一些信息。

如果您了解C ++,那么将Java视为仅具有虚拟方法(和静态方法),并且处理查找到vtable非常简单,因为继承钻石或其他恶意案例没有问题。

当使用接口的实现时,它几乎相同,只是进行了更复杂的查找(即,首先查找vtable中的索引,然后再继续进行)。但是,拥有一个实现接口的对象意味着必须有一些完全实现接口的类,这一点再次相对简单。请记住,所有非常复杂的东西都是在编译时完成的;在运行时,事情在所有情况下都相对简单。

那么,你会利用这些吗?好吧,你应该(实际上你会发现在实际代码中很难避免)。根据接口或超类定义的合同来考虑这是一种好的方式,其中子类型在没有调用者必须知道细节的情况下遵守合同。 Java库非常重要,特别是因为合同类型细节的可见性及其实现可能不同。所有客户端代码都知道对象服从合同,它是给定类型的。

你提出的其他问题几乎都被其他人回答,并且在许多其他面向对象的语言中也有相同的答案。

据我所知,您使用接口来解耦代码。您希望针对接口而不是实现进行编程:"编程到接口"是什么意思?您将使用抽象类来实现functionlity,这对于所有实现类来说都是微不足道的,因此您不需要在所有实现类中编写它。

根据您的背景,C ++或Java的东西会变得非常混乱。

在C ++中,存在虚函数的概念,在运行时查找它以决定函数属于哪个实际类。还有一些非虚函数将根据变量类型调用。

在Java中虽然所有方法本质上都是虚拟的,这意味着Java方法总是在运行时查找,这个过程称为Runtime Polymorphism

这样做的好处就是这样

class Animal{

public void type(){

System.out.println("animal");

}

}

class Dog extends Animal{

public void type(){

System.out.println("dog");

}

}

class Cat extends Animal{

public void type(){

System.out.println("cat");

}

}

public class Driver{

public static void main(String[] args){

Animal[] animals = new Animal[3];

animals[0] = new Animal();

animals[1] = new Dog();

animals[2] = new Cat();

for(Animal animal: animals){

animal.type();

}

}

}

这将输出

animal

dog

cat

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值