【发布时间】:2009-12-23 06:53:31
【问题描述】:
可以在 Java 中创建抽象类的对象
【问题讨论】:
-
这是一个初学者问题,但有效。
-
良好的形式和 SO 社区的金星,因为没有 lmgtfy 答案,以及一些有用的简单解释。
标签: java oop abstract-class
可以在 Java 中创建抽象类的对象
【问题讨论】:
标签: java oop abstract-class
如果你有这样的抽象类:
public abstract class Foo
{
public void bar()
{
car();
}
protected abstract void car();
}
如果你能做到这一点:
final Foo foo;
foo = new Foo();
foo.bar();
当“bar”方法调用“car”方法时会发生什么,因为“car”方法没有与之关联的代码?
你可以这样做:
class Star
extends Bar
{
protected void car()
{
}
}
然后做:
final Foo foo;
foo = new Star();
foo.bar();
这次你有一个 Foo 类型的变量,它可以保存 Foo 的任何具体子类(非抽象类是具体的)。现在,当您调用“bar”方法时,它使用 Foo 中的方法,而当调用“car”方法时,它使用 Star 中的方法。这是多态性的一个例子。
【讨论】:
除非您提供其所有抽象方法的实现(通过实现匿名内部类),否则实例化抽象类的尝试将在编译时失败:
Runnable r = new Runnable() {
public void run() {
//do something
}
};
【讨论】:
假设这是一个完整的新手问题,以下是 Java 中的抽象类:
java 中的类主要分为三种类型,接口、抽象类和类。这些中的每一个都为实际的类定义添加了一些特定的东西;
使用任何可能的类类型有很多原因,但最常见的是在现代 Java 代码中,您会看到很多接口和一堆实现这些接口的类。
示例:类
考虑以下类:
public class Cat {
public void speak() {
System.out.println("Meow!");
}
public void eat(Food f) {
System.out.println("Om nom nom, this "+f.getName()+" is delicious!");
}
}
这是一个非常简单的类,是每个 Java 程序员,甚至是初学者都熟悉的类。这里没什么特别的。然而,有了这个你有一个问题:如果你有一个基本相同的Dog,但它显然是吠叫而不是喵喵叫?
示例:抽象类
“Cat 或 Dog”问题可以通过继承来解决。传统的标准继承如下所示:
public class Animal {
public void eat(Food f) {
System.out.println("Om nom nom, this "+f.getName()+" is delicious!");
}
}
public class Cat extends Animal {
public void speak() {
System.out.println("Meow!");
}
}
public class Dog extends Animal {
public void speak() {
System.out.println("Bark! Bark!");
}
}
但是这里有一个问题:要真正让Cat 喵或Dog 吠,你必须有代码来检查动物到底是什么动物,将其转换为正确的类型,然后调用方法:
if (animal instanceof Dog) {
((Dog) animal).speak();
} else if (animal instanceof Cat) {
((Cat) animal).speak();
}
如您所见,这种代码完全没有意义!我们当然希望能够直接致电animal.speak(),对吧?为此,我们有抽象类!通过用这个替换上面示例中的Animal 类
public abstract class Animal {
public void eat(Food f) {
System.out.println("Om nom nom, this "+f.getName()+" is delicious!");
}
public abstract void speak();
}
您只需拨打animal.speak() 即可让您的Dog 吠叫和Cat 喵喵叫!很好,不是吗?
请注意,您还可以将speak() 的默认行为定义为Animal,然后在Cat 和Dog 中覆盖该方法,有时这甚至比我刚才在这里展示的更有意义。
不管怎样,另一个问题出现了:如果你的Dog 是一个Animal 也是一个Pet 怎么办? Java 只允许单一继承以避免diamond inheritance problem,因此您不能只为它们拥有另一个超类。您可以将其添加为 Animal 的超类,但话又说回来,并非所有动物都是宠物 - 我的院子池塘里肯定没有河马!
示例:界面
由于接口仅定义行为而不是实际实现它们(这实际上是相关的关键字!)你可以使用接口来定义额外的对你原来的班级的行为。让我们假设宠物通常可以被修饰,所以Pet 的界面是这样的:
public interface Pet {
void groom(Brush b);
}
现在只需将implements Pet 添加到您的Dog,它现在就可以修饰了!只是为了确保,Dog 类的第一行应该是这样的:
public class Dog extends Animal implements Pet {
现在要修饰您的Dog 或任何其他Pet,您可以这样做:
if (animal instanceof Pet) ((Pet) animal).groom();
差不多就是这样。作为练习,尝试将Animal 实现为接口;请注意,接口实际上可以扩展其他接口。
PS。枚举和匿名内部类也可以被视为类类型,但是它们并不是每个人在学习 Java 基础知识后都应该知道的主要类型。
【讨论】:
你不能实例化一个抽象类(在它上面调用new),如果这就是你的意思的话。
可以有子类的实例。这些对象也是 instanceof 抽象类,这意味着您可以将它们强制转换为它。
【讨论】:
这取决于你的意思。
如果你的意思是:“我可以有一个抽象类的实例吗”——当然; (抽象类的)具体子类的任何实例都隐含地是抽象超类型的实例。
如果您的意思是:“我可以在不定义具体子类型的情况下拥有一个抽象类的实例吗”——是的,如果某个库(例如 javassist、cglib)为您生成具体子类型。
如果您的意思是“以下表达式是否会通过”:
assert Modifier.isAbstract(x.getClass().getModifiers());
答案是否定的。
【讨论】:
看看吧。它的干净和体面javacanal.blogspot.com/
【讨论】:
没有。这是不可能的。你需要创建一个扩展抽象类的类,然后你可以创建一个子类的对象。
请查找示例:
abstract class AbstractClass{
public abstract String abstractMethod(String param1,String param2);
public void nonAbstractMethod(String param){
System.out.println("Value of param is "+param);
}
}
class NonAbstractClass extends AbstractClass{
public String abstractMethod(String param1,String param2){
String param = param1 + param2;
return param;
}
}
public class DemoClass{
public static void main(String[] args) {
NonAbstractClass nonAbstractClass = new NonAbstractClass();
nonAbstractClass.abstractMethod("param1", "param2");
nonAbstractClass.nonAbstractMethod("param1");
}
}
【讨论】: