【问题标题】:abstract-class in javajava中的抽象类
【发布时间】:2009-12-23 06:53:31
【问题描述】:

可以在 Java 中创建抽象类的对象

【问题讨论】:

  • 这是一个初学者问题,但有效。
  • 良好的形式和 SO 社区的金星,因为没有 lmgtfy 答案,以及一些有用的简单解释。

标签: java oop abstract-class


【解决方案1】:

如果你有这样的抽象类:

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 中的方法。这是多态性的一个例子。

【讨论】:

    【解决方案2】:

    除非您提供其所有抽象方法的实现(通过实现匿名内部类),否则实例化抽象类的尝试将在编译时失败:

    Runnable r = new Runnable() {
        public void run() {
            //do something
        }
    };
    

    【讨论】:

    • 您可能使用过一个包含抽象类的示例(Runnable 是一个接口)... :)
    【解决方案3】:

    假设这是一个完整的新手问题,以下是 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,但它显然是吠叫而不是喵喵叫?

    示例:抽象类

    CatDog”问题可以通过继承来解决。传统的标准继承如下所示:

    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,然后在CatDog 中覆盖该方法,有时这甚至比我刚才在这里展示的更有意义。

    不管怎样,另一个问题出现了:如果你的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 基础知识后都应该知道的主要类型。

    【讨论】:

      【解决方案4】:

      你不能实例化一个抽象类(在它上面调用new),如果这就是你的意思的话。

      可以有子类的实例。这些对象也是 instanceof 抽象类,这意味着您可以将它们强制转换为它。

      【讨论】:

        【解决方案5】:

        这取决于你的意思。

        如果你的意思是:“我可以有一个抽象类的实例吗”——当然; (抽象类的)具体子类的任何实例都隐含地抽象超类型的实例。

        如果您的意思是:“我可以在不定义具体子类型的情况下拥有一个抽象类的实例吗”——是的,如果某个库(例如 javassist、cglib)为您生成具体子类型。

        如果您的意思是“以下表达式是否会通过”:

        assert Modifier.isAbstract(x.getClass().getModifiers());
        

        答案是否定的。

        【讨论】:

          【解决方案6】:

          看看吧。它的干净和体面javacanal.blogspot.com/

          【讨论】:

            【解决方案7】:

            没有。这是不可能的。你需要创建一个扩展抽象类的类,然后你可以创建一个子类的对象。

            请查找示例:

            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");
                }
            }
            

            【讨论】:

            • 是与否...扩展抽象类的类本身必须不是抽象的,才能做到这一点。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-12-06
            • 2011-08-24
            • 1970-01-01
            • 1970-01-01
            • 2016-07-21
            相关资源
            最近更新 更多