Java:理解接口的目的有困难吗?

Java:理解接口的目的有困难吗?,java,interface,Java,Interface,我最近被介绍到Java中的接口,但我很难理解它们的用途。那么,假设我有以下几点: //this is an interface public interface DanceMoves { public void theJitterbug(int twists); public void theHustle(int steps); public void theMoonwalk(int slides); } 然后我有一个实现这个接口的类: public class Dan

我最近被介绍到Java中的接口,但我很难理解它们的用途。那么,假设我有以下几点:

//this is an interface
public interface DanceMoves {
    public void theJitterbug(int twists);
    public void theHustle(int steps);
    public void theMoonwalk(int slides);
}
然后我有一个实现这个接口的类:

public class DanceClub implements DanceMoves {
    public void theJitterbug(int twists) {
        System.out.println("Twist " + twists + " times!");
    }
    public void theHustle(int steps) {
        System.out.println("Step " + steps + " times!");
    }
    public void theMoonwalk(int slides) {
        System.out.println("Slide " + slides + " times!");
    }

    //more methods can go here

    public static void main(String[] args) {
        DanceClub letsDance = new DanceClub();
        letsDance.theJitterbug(5);
        letsDance.theHustle(4);
        letsDance.theMoonwalk(3);
    }        
}
public class Diner implements DanceMoves {
    public void theJitterbug(int twists) {
        System.out.println("Twist " + twists + " times!");
        System.out.println("We only do the jitterbug in diners!");
    }

    public void theHustle(int steps) {
    }

    public void theMoonwalk(int slides) {
    }

    public static void main(String[] args) {
        Diner letsDanceAgain = new Diner();
        letsDanceAgain.theJitterbug(5);
    }
}
也许我还有另一种实现这个接口的方法:

public class DanceClub implements DanceMoves {
    public void theJitterbug(int twists) {
        System.out.println("Twist " + twists + " times!");
    }
    public void theHustle(int steps) {
        System.out.println("Step " + steps + " times!");
    }
    public void theMoonwalk(int slides) {
        System.out.println("Slide " + slides + " times!");
    }

    //more methods can go here

    public static void main(String[] args) {
        DanceClub letsDance = new DanceClub();
        letsDance.theJitterbug(5);
        letsDance.theHustle(4);
        letsDance.theMoonwalk(3);
    }        
}
public class Diner implements DanceMoves {
    public void theJitterbug(int twists) {
        System.out.println("Twist " + twists + " times!");
        System.out.println("We only do the jitterbug in diners!");
    }

    public void theHustle(int steps) {
    }

    public void theMoonwalk(int slides) {
    }

    public static void main(String[] args) {
        Diner letsDanceAgain = new Diner();
        letsDanceAgain.theJitterbug(5);
    }
}
所以我的问题是,如果我们必须重写所有的接口方法,为什么我们还要麻烦实现接口呢?这是如何重用代码的

编辑:感谢所有回答的人!我是Java新手,到目前为止我唯一学过的另一种语言是Jython。所以,虽然很多概念都翻译得很好,但一些新的东西对我来说有点难理解

我还感谢下面给出的回复示例,以及与以前的问题和外部来源的链接。事实上,我之前已经阅读了这些问题的大部分,并且访问了那些外部来源,但是在我能够更清楚地理解我实际阅读的内容之后,这些问题会更有帮助

无论如何我真正想做的是写下我关于接口的重要收获(为了我和子孙后代),看看我是否真的“明白”。我以前的问题是,如果我们必须重写所有的接口方法,为什么还要麻烦实现接口?这是如何重用代码的?。使用Elliot Frisch对我的示例的修订:

public interface Dance { //an interface
  public void boogie(int count);
}
现在,您可以拥有实现此接口的方法,无论是否相关-

public class theMoonwalk implements Dance {
  public void boogie(int count) {
    System.out.println("Slide " + count + " times!");
  }
  public void mJ() {
    System.out.println("Michael Jackson did this dance!");

}
public class theHustle implements Dance {
  public void boogie(int steps) {
    System.out.println("Step " + steps + " times!");
  }
}
public class theJitterBug implements Dance {
  public void boogie(int twists) {
    System.out.println("Twist " + twists + " times!");
  }
}

public class crazyUncle implements Dance {
  public void boogie(int shimmy) {
    System.out.println("I really don't know how to dance.");
  }

  public void yap() {
    System.out.println("When I was your age...!");
  }
}
然后用它,

public static void main(String[] args) {

  Dance[] dances = new Dance[] {
      new theHustle(), new theMoonwalk(), new theJitterBug(), new crazyUncle()
  };
  for (Dance d : dances) { //for each element in this array of type Dance...
    // Note: The caller just boogies. The object determines the "move".
    d.boogie(3);
  }
}
public static void main(String[] args) {
  Dance[] dances = new Dance[] {
      new TheHustle(), new TheMoonwalk(), new TheJitterBug()
  };
  for (Dance d : dances) {
    // Note: The caller just gets down. The object determines the "move".
    d.getDown(3);
  }
}
现在,我来解释一下,如果我必须重写所有的接口方法,为什么我要费心实现一个接口:

因为theHustle、Moonwalk、Jitterbug和crazyUncle类都实现了舞蹈接口,所以它们实际上“签署了”一份“合同”,保证这些类的实例至少包含舞蹈接口中的方法。 因此,例如,尽管theMoonwalk类与CrazynCle类不同,但Moonwalk对象和CrazynCle对象可以包含在类型舞蹈的数组中,因为这些对象包含舞蹈接口的“DNA”

此外,我可以在另一个类中使用另一个方法,该方法接受Dance类型的参数:

public void danceExercise(Dance d, int num) {        
    d.boogie(num); 
}

调用danceExercise方法时,对于Dance d参数,我可以提供实现Dance接口的任何类型的值。因此,由于CrazynCle和theMoonwalk都实现了舞蹈,我可以提供一个CrazynCle或theMoonwalk的实例,其中需要舞蹈


TL;谢谢大家!我现在对接口有了更深刻的理解。

正如rahul pasrich和ra2085所指出的,关于这个主题有很多信息。为了更直接地回答您的问题,您可以做一些事情,比如接受DanceMoves类型的参数,而不关心它在哪里实现。你可能有6种不同类型的舞蹈动作,以及一个单独的化身对象。这是接口的关键概念之一。

接口允许方法确信您传递给它的内容是兼容的。因此,它允许您编写如下代码:

interface Animal
{
    public String getSound();
}
public void makeSound(Animal animal) { /*make the sound, using animal.getSound()*/}
并且有两个类
Cat
lizard
实现这个接口,它们将分别定义方法
getSound()
的作用。因此,假设您有这样一种方法:

interface Animal
{
    public String getSound();
}
public void makeSound(Animal animal) { /*make the sound, using animal.getSound()*/}
该方法可以确保实现
Animal
的任何类都必须具有定义的声音,因为该声音是
Animal
的属性,因此在实现
Animal
时可以安全地传入
Lizard
Cat
。这样可以避免您发出
makeSound(猫)
makeSound(蜥蜴)

这意味着您正在重用代码,只是不同的代码(只需定义一次
makeSound()
方法!)。想象一下,这是一种契约形式,它确保对象与方法兼容

你的问题实际上是一个完美的例子,说明了为什么接口是有用的,但让我们“点击”一下要点

public void theJitterbug(int twists) {
    System.out.println("Twist " + twists + " times!");
}
public void theHustle(int steps) {
    System.out.println("Step " + steps + " times!");
}
public void theMoonwalk(int slides) {
    System.out.println("Slide " + slides + " times!");
}
都是舞蹈!所以,让我们这样称呼他们

public interface Dance {
  public void getDown(int count);
}
现在,你可以-

public class TheMoonwalk implements Dance {
  public void getDown(int count) {
    System.out.println("Slide " + count + " times!");
  }
}
public class TheHustle implements Dance {
  public void getDown(int steps) {
    System.out.println("Step " + steps + " times!");
  }
}
public class TheJitterBug implements Dance {
  public void getDown(int twists) {
    System.out.println("Twist " + twists + " times!");
  }
}
然后使用它

public static void main(String[] args) {

  Dance[] dances = new Dance[] {
      new theHustle(), new theMoonwalk(), new theJitterBug(), new crazyUncle()
  };
  for (Dance d : dances) { //for each element in this array of type Dance...
    // Note: The caller just boogies. The object determines the "move".
    d.boogie(3);
  }
}
public static void main(String[] args) {
  Dance[] dances = new Dance[] {
      new TheHustle(), new TheMoonwalk(), new TheJitterBug()
  };
  for (Dance d : dances) {
    // Note: The caller just gets down. The object determines the "move".
    d.getDown(3);
  }
}

面试时我最喜欢问的问题


如果您得到了策略模式,那么您也可以解释其他模式

Java中的继承包含两个概念。如果X从Y继承,这意味着

  • X可以代替Y,这意味着对X的引用可以在任何需要引用Y的地方使用

  • X的实例可以使用继承的Y成员的成员作为自己的成员

  • Java运行时只允许类使用从其他类型继承的成员,就像它们是自己的一样。因此,一个类只能从另一个类继承。另一方面,没有理由认为一个类不能执行许多不同的规则,可以替代许多不同的不相关的东西


    接口允许定义替换类,这样要求实现特定接口的代码将能够接受对实现该接口的任何类型的对象的引用。因为实现接口的类在历史上被要求实现所有接口成员本身,所以实现接口的类除了能够传递给期望接口类型的代码之外,没有从这些接口继承任何东西,因此,单一继承的运行时限制不会对实现多个接口的类造成任何阻碍。

    请看这一点,这个答案可能会有所启发。接口不是(直接)用于代码重用的。它们用于不同的行为。特定的问题与Java无关。请学习“接口”概念一