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