Java 为什么界面有用?

Java 为什么界面有用?,java,interface,abstract-class,Java,Interface,Abstract Class,我确切地知道接口和抽象类之间的区别,但是为什么接口有用呢?看看这个: 想象一下,有人在使用您的库时想要引入其他可用的东西,例如MovableTirangle。如果他们让这个实现可移动,它可以完美地与您的库一起使用 例如,库提供了 void move(Movable m, int horiz, int vert) { int i; if (horiz >= 0) { for (i=0; i < horiz; i++) { m.mo

我确切地知道接口和抽象类之间的区别,但是为什么接口有用呢?看看这个:

想象一下,有人在使用您的库时想要引入其他可用的东西,例如
MovableTirangle
。如果他们让这个实现
可移动
,它可以完美地与您的库一起使用

例如,库提供了

void move(Movable m, int horiz, int vert) {
    int i;
    if (horiz >= 0) {
        for (i=0; i < horiz; i++) {
            m.moveRight();
        }
    } else {
        for (i=0; i > horiz; i--) {
            m.moveLeft();
        }
    }
    if (vert >= 0) {
        for (i=0; i < vert; i++) {
            m.moveUp();
        }
    } else {
        for (i=0; i > vert; i--) {
            m.moveDown();
        }
    }
}
void move(可移动m、水平内、垂直内){
int i;
如果(水平方向>=0){
对于(i=0;ihoriz;i--){
m、 左移();
}
}
如果(垂直方向>=0){
对于(i=0;ivert;i--){
m、 向下移动();
}
}
}
可用于所有当前和未来类型的
移动式
s

到目前为止,这对基类也是有效的,所以这并不重要

但是,由于Java不支持多重继承,一个类不能从多个基类继承。但如果需要的话,它可以实现多个接口


此外,如果您有一个函数接口(您没有,因为其中有多个非默认函数),您还可以使用Java的新lambda特性。这是另一件不适用于抽象类的事情。

现在想象一下抽象
。您如何实现
可移动点
既是
可移动的
又是
?只有接口才能提供这种功能,这就是它们在这里的目的。

是的——在本例中,您可以提供,但也可以尝试从更大的角度来看。当我第一次学习OOP和接口时,我问了同样的问题,这让我困惑了很长一段时间

如果您想将“movable”方法添加到不是Point子类的对象,比如说“MovableJPEG”之类的东西,该怎么办。移动操作的最终结果是相同的,但是您必须重写这两个类和不同方法的接口,以便在与可移动对象交互的类中处理这些特性的移动


对于一个接口,您可以传递任意数量的类型,这些类型仅通过具有与相同方法相似的接口来实现,因为它们的实现细节保证是相同的。

接口和抽象类都允许程序员编写模块化类

与抽象类相比,接口的优点在于它不携带任何预定义的方法或属性。抽象类可能有您不希望在类内部实现的内容

第二个优点是java类只能扩展一个类,但可以扩展大量接口

接口提供了更多的自由,抽象类可以影响类的内部设计。抽象类的一个优点是代码共享,这对于接口来说更加困难

  • java中没有多重继承。因此,不能在同一个类中继承多个类,但可以实现多个接口
  • 有助于使事情有条理。就像所有与狗相关的东西都在一个界面下一样,所有的猫都在猫的界面下,以此类推
  • 运行时多态性:使用接口u可以有超类引用变量引用不同的子类。这有助于保持代码整洁,提高可伸缩性(使所有那些本来可能不存在的桥接/代理/工厂等设计模式成为可能)
  • 请参见

    • 如果您认为将计划使用继承,那么抽象类是好的,因为它为 派生类
    • 如果您希望能够声明非公共成员,抽象类也很好。在接口中,所有方法都必须是公共的
    • 如果您认为将来需要添加方法,那么抽象类是更好的选择。因为如果你添加新的方法 指向一个接口的标题,然后是所有已经存在的类 实现该接口将必须更改以实现新的 方法。那可能会很麻烦
    • 当您认为API在一段时间内不会改变时,接口是一个不错的选择
    • 当您想拥有类似于多重继承的东西时,接口也很好,因为您可以实现多个接口
    因此,在您的场景中,仅通过接口,您可以指定可移动点是否同时是可移动点和点。

    概念差异: 我不会列出使用接口或抽象类之间的所有区别,也不会列出何时使用它们,我认为您会在web上找到很多资源,因此仅讨论这一点,作为示例:

    要回答您,,您可以在示例中只使用抽象类,而不必使用接口

    但是有一个概念上的区别,创建接口不是为了公开公共行为,它是一个类可以做什么的契约。 抽象类是层次结构的父类,用于生成具有核心结构并提供默认行为的子类

    与你的例子类似: 从概念上讲,
    Movable
    必须是一个
    接口,因为它定义了
    实现Movable
    的类可以做什么(可以上移、下移、下移…),而不是如何做(圆不能像矩形那样移动)。而您的
    movablecycle
    可以是一个
    抽象类
    ,因为我们可以定义如下方法:
    calculateArea()
    getRadius()
    calculateCircumference()
    。。。这是继承自它的类的默认行为,如
    movableweel

    <Bounceable> / \ Ball Tire
    static void Main(string[] args)
        {
            IanimalBehavior pluto = new Dog();
            IanimalBehavior simba = new Cat();
    
            Program.makeAnimals_say_and_eat(pluto);
            Program.makeAnimals_say_and_eat(simba);
    
            Program.makeAnimals_say_and_eat(pluto);
            Program.makeAnimals_say_and_eat(simba);
            Console.ReadLine();
        }
    
        static void makeAnimals_say_and_eat(IanimalBehavior animalObject)
        {
            Console.WriteLine(animalObject.makeSound());
            Console.WriteLine(animalObject.eat());
        }
    
        interface IanimalBehavior {
           string makeSound();
           string eat();
        } 
    
        class Dog : Animal, IanimalBehavior {            
    
            public string makeSound() {
                return this.GetType().Name + " says: wuf";
            }
        }
    
        class Cat : Animal, IanimalBehavior {
    
            public string makeSound()
            {
                return this.GetType().Name + " says: miauw";
            }
        }
    
        abstract class Animal {
    
            bool _isFull = false;
            public string eat()
            {
                if (_isFull == false)
                {
                    _isFull = true;
                    return this.GetType().Name + " is now eating";
                }
                else
                {
                    return this.GetType().Name + " is now too full to eat!";
                }
            }
        }
    
    IanimalBehavior pluto = new Dog();
    
    static void makeAnimals_say_and_eat(IanimalBehavior animalObject)
        {
            Console.WriteLine(animalObject.makeSound());
            Console.WriteLine(animalObject.eat());
        }
    
    interface IanimalBehavior {
           string makeSound();
           string eat();
        } 
    
    Program.makeAnimals_say_and_eat(pluto);
    Program.makeAnimals_say_and_eat(simba);
    
    Program.makeAnimals_say_and_eat(pluto);
    Program.makeAnimals_say_and_eat(simba);
    
    Dog says: wuf
    Dog is now eating
    Cat says: miauw
    Cat is now eating
    Dog says: wuf
    Dog is now too full to eat!
    Cat says: miauw
    Cat is now too full to eat!
    
    IanimalBehavior[] animal_list = { new Dog(), new Cat()};
    
    foreach (IanimalBehavior animal in animal_list)
           {
               Console.WriteLine(animal.eat());
               Console.WriteLine(animal.makeSound());
           }