【问题标题】:Java: Trouble understanding the purpose of interfaces?Java:难以理解接口的用途?
【发布时间】:2014-08-21 09:25:02
【问题描述】:

最近有人向我介绍了 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);
    }
}

所以我的问题是,如果我们必须重写所有接口方法,为什么还要费心去实现一个接口呢?这是如何复用代码的?

编辑:非常感谢所有回答的人!我是 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);
  }
}

现在,如果我必须重写所有接口方法,为什么我应该费心实现接口,这是我的解释:

因为 theHustle、theMoonwalk、theJitterbug 和 crazyUncle 类都实现了 Dance 接口,所以它们实际上“签署”了一份“合同”,保证这些类的实例至少包含来自舞蹈界面。 因此,即使 theMoonwalk 类与 crazyUncle 类不同,例如 theMoonwalk 对象和 crazyUncle 对象也可以包含在 Dance 类型的数组中,因为这些对象包含 Dance 接口的“DNA”。

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

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

}

在调用 danceExercise 方法时,对于 Dance d 参数,我可以提供任何实现了 Dance 接口的类型的值。因此,由于 crazyUncle 和 theMoonwalk 都实现了 Dance,我可以提供一个 crazyUncle 的实例或一个期望有 Dance 的 theMoonwalk 的实例。

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

【问题讨论】:

标签: java interface


【解决方案1】:

您的问题实际上是 encapsulates 一个完美的例子,说明接口为什么有用 - 但让我们“轻敲”一下,

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()
  };
  for (Dance d : dances) {
    // Note: The caller just gets down. The object determines the "move".
    d.getDown(3);
  }
}

【讨论】:

  • 我认为事情开始明朗了……在您的示例中,主要方法将打印:Slide 3 times!步骤 3 次!扭转3次!对吗?
  • 步进、滑动、扭转。但这就是一般的想法。
【解决方案2】:

正如 rahul pasrich 和 ra2085 所指出的,有很多关于该主题的信息。为了更直接地回答您的问题,您可以执行诸如采用 DanceMoves 类型的参数之类的操作,而不必关心它是在哪里实现的。您可能有 6 种不同类型的舞蹈动作,以及您将它们发送到的单个 Avatar 对象。这是Polymorphism 的关键概念之一。

【讨论】:

    【解决方案3】:

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

    interface Animal
    {
        public String getSound();
    }
    

    并且有两个类Catlizard 实现了这个接口,然后它们将分别定义方法getSound() 的作用。因此,假设您有这样的方法:

    public void makeSound(Animal animal) { /*make the sound, using animal.getSound()*/}
    

    该方法可以确保任何实现Animal 的类都必须具有定义的声音,因为这是Animal 的属性,因此在实现@ 时传入LizardCat 是安全的987654330@。这使您免于制作makeSound(Cat cat)makeSound(Lizard lizard)

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

    【讨论】:

      【解决方案4】:

      我最喜欢问的面试问题

      https://en.wikipedia.org/wiki/Strategy_pattern

      如果你掌握了策略模式,那么你也可以解释其他人

      【讨论】:

        【解决方案5】:

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

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

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

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2014-12-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-01-15
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多