Java 子类特定的代码-我应该使用抽象基类方法还是接口?
我有一个超级类,动物,有两个子类,猫和狗。狗和猫都需要有特定的说话和移动方法。以下是实现这一目标的两个备选方案:Java 子类特定的代码-我应该使用抽象基类方法还是接口?,java,methods,implementation,abstract,overriding,Java,Methods,Implementation,Abstract,Overriding,我有一个超级类,动物,有两个子类,猫和狗。狗和猫都需要有特定的说话和移动方法。以下是实现这一目标的两个备选方案: Animal将有两个抽象方法,move()和speak();Dog、Cat和Dog都会覆盖这两种方法,因此它们是特定于它们的 我可以有一个具有通用动物方法move()和speak()的接口,其中两个子类实现了这些方法,因此它们又是特定于它们的 这些方法中的一种比另一种更合适吗?我意识到如果我有一个动物列表,我会写: ArrayList Animal<allAnimals>
ArrayList Animal<allAnimals> = new ArrayList <Animal>():
allAnimals.add(new Dog());
allAnimals.add(new Cat());
//If I override the methods, I can simply go:
for (Animal a: allAnimals) a.move();
//Where as if I implemented the methods, I would not need be able to do this. I would need to cast the animal as its specific animal. e.g. If I knew the animal was a dog.
Dog aDog= (Dog) a;
a.move();
ArrayList Animal=new ArrayList():
添加(新狗());
添加(新的Cat());
//如果我重写这些方法,我可以简单地执行以下操作:
对于(动物a:所有动物)a.移动();
//如果我实现了这些方法,我就不需要这样做。我需要将动物塑造成它的特殊动物。e、 如果我知道那动物是狗。
狗aDog=(狗)a;
a、 move();
因此,重写和实现可能有一定的优势和劣势,这取决于它们所使用的情况。还有谁能详细说明一下吗 一般来说,如果一个Java类可以实现多个接口,但只能扩展一个类,那么经验法则是使用一个接口 只有当几个类有很多共同点并且您希望能够重用相同的代码时,才应该使用扩展(继承) 顺便说一下,在作为示例提供的代码中,您可以使用:
for (Animal a: allAnimals) a.move();
无论是在使用接口还是继承的情况下。一般来说,经验法则是使用一个接口,前提是Java类可以实现多个接口,但只扩展一个类 只有当几个类有很多共同点并且您希望能够重用相同的代码时,才应该使用扩展(继承) 顺便说一下,在作为示例提供的代码中,您可以使用:
for (Animal a: allAnimals) a.move();
无论是在使用接口还是继承的情况下。作为一般的经验法则,使用扩展(抽象类),如果且仅当您的扩展类将共享大量行为时。在这种情况下,可以使用扩展来消除重复代码的需要,这是一件好事(TM) 另一方面,如果您的类只需要具有相同的签名,那么就使用一个更灵活的接口(例如,您可以实现多个接口,但只能从一个类进行扩展) 这只是一些一般性的建议,因为每个用例都是不同的。 为了避免扩展的限制,可以使用其他技术,例如composition:() 最后但并非最不重要的一点,我认为您的代码有点错误。
无论基类是从抽象类继承还是从接口继承,您都可以用完全相同的方式调用基类上的方法。作为一般经验法则,使用扩展(抽象类),前提是您的扩展类将共享大量行为。在这种情况下,可以使用扩展来消除重复代码的需要,这是一件好事(TM) 另一方面,如果您的类只需要具有相同的签名,那么就使用一个更灵活的接口(例如,您可以实现多个接口,但只能从一个类进行扩展) 这只是一些一般性的建议,因为每个用例都是不同的。 为了避免扩展的限制,可以使用其他技术,例如composition:() 最后但并非最不重要的一点,我认为您的代码有点错误。
您可以用完全相同的方式调用基类上的方法,无论它们是从抽象类还是从接口继承。首先,从子类的角度来看,重写或实现方法之间没有区别。所以,在所有情况下,您编写的代码都将完全相同(在java中,所有方法都像C++ ++代码>虚拟<代码>函数;调用的方法是引用的实际类之一)。 因此,决定是定义一个超类,它是一个接口、一个抽象类或一个可实例化类 如果有必要创建超类的对象(
newanimal()
),则应使用instantiable类
抽象类,当没有超类的对象,但某些方法的实现将由所有(或几乎所有)子类共享时
接口,当您只定义契约时,实现留给每个子类
这取决于问题的范围来决定使用哪种方法。例如,如果
move()
只是表示“更改动物的x,y坐标”,那么它可能应该是抽象类中的一个实现方法。但是如果你必须定义动物是如何移动的,那么animal
将是一个更好的接口,这样每个子类都可以定义它。首先,从子类的角度来看,重写或实现一个方法是没有区别的。所以,在所有情况下,您编写的代码都将完全相同(在java中,所有方法都像C++ ++代码>虚拟<代码>函数;调用的方法是引用的实际类之一)。
因此,决定是定义一个超类,它是一个接口、一个抽象类或一个可实例化类
如果有必要创建超类的对象(newanimal()
),则应使用instantiable类
抽象类,当没有超类的对象,但某些方法的实现将由所有(或几乎所有)子类共享时
接口,当您只定义契约时,实现留给每个子类
这取决于项目的范围
static public abstract class Animal implements MoverAndSpeaker {
@Override
public abstract void move();
public abstract void speak();
}