0

For example: Foo ab=new Dog();

Saving object of another type class to reference of another class!

4

7 回答 7

2

Yes if Foo is an interface then this approach gives you more control on your code. You achieve Polymorphism, Plug-ability, Maintainability and Loose coupling characteristics of java programming language.

Let's say if you are supposed to connect to oracle from your application and written the code like this

    OracleDrive driver= new OracleDriver()
    driver.connect();

it will solve your problem. But will make your code tightly coupled with OracleDriver. Your application won't compile at all if you remove Oracle related jar from your classpath. And if someone ask you make your app connect to different DBs based on their configuration then you end up with multiple ifs based on your application supported DBs. which is bad practice as per programming standards.

If you all DB drives implements an interface Driver then you can load driver based on configuration without tightly coupling your code to any specific driver class like this

Driver driver = properties.get(db.driver.class)
driver.connect()

Now you see that you need to change you application to connect to MySql you just need to set that class in your configuration file.

Hope you got my point!

于 2013-10-07T05:48:20.093 回答
2

并不总是需要做类似Foo foo = new Bar()的事情,但通常建议参考接口而不是实现。这样您就可以更改您的实现,而无需更改其他代码。例如,如果您使用 Lists 做某事并使用 ArrayLists,您可能会这样做:

ArrayList<Integer> numbers = new ArrayList<>();
//Do stuff with numbers

但是,您可能不在乎它是哪种列表,因此您可能会更好

List<Integer> numbers = new ArrayList<>();
//Do stuff with numbers

现在,你拥有什么样的 List 并不重要,也许你会发现使用 LinkedList 可以获得更好的性能,你可以使用它而不是更改任何其他代码。

我想说的是,当其他调用者接收对象时,多态性是最重要的。

于 2013-10-07T05:01:33.857 回答
1

它对方法参数更有用。

class Animal {
    public boolean hasHair = true;
    public void speak() {}
}

class Dog extends Animal {
    public void speak() {
        System.out.println("Woof!");
    }
}

class Person {
    public void shave(Animal a) {
        a.hasHair = false;
        a.speak();
    }
}

class Main {
    public static void main(String[] args) {
        Person joe = new Person();
        Dog fido = new Dog();
        joe.shave(fido);
    }
}

在这种情况下,Person 可以为任何 Animal 剃毛,但我们将它传递给 Dog。

Animal fido = new Dog();会不太有用,因为我们知道 fido 是一只狗,但考虑一下:

Animal pet;
if(joe.prefersCats)
    pet = new Cat();
else
    pet = new Dog();
于 2013-10-07T05:06:15.843 回答
0

简单的回答,你不能那样做。

更复杂的答案,只有当 'Dog' 是 'Foo' 的类型时,你才能做到这一点。我们什么时候说 Dog 是 'Foo' 的类型是 Dog 是实现 Foo(如果是接口)还是扩展 Foo(如果是另一个类或抽象类)

现在,利用 Coding to Interfaces(您的问题的技术名称)的优势是

1)Java 的多态性基于此(多态性使行为的运行时变化成为可能,请在 java 中搜索多态性以获取更多信息) 2)您正在通过这种方法使接口独立于实现。

希望这回答了你的问题。

于 2013-10-07T05:06:43.130 回答
0

这种类型的声明是唯一可能的

 Foo ab=new Dog();

如果 Dog 类扩展类 Foo 或 Foo 是由 Dog 类实现为的接口

class Dog extends Foo { .... }

或者

class Dog implements Foo { ... } //Here Foo is an interface

我认为,如果您将具有继承接口或继承类的类对象初始化为所有基类函数,那么属性将在您的派生类对象中可用。如果您要初始化具有相同基类和不同派生类的多个对象,这种类型的声明将派上用场。
例如,

public class MyObject
{
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

public class MyFile extends MyObject
{
    private String extension;

    public String getExtension() {
        return extension;
    }

    public void setExtension(String extension) {
        this.extension = extension;
    }
}

public class MyFolder extends MyObject
{

}

如果你正在初始化

MyObject file = new MyFile();

这确实没有用,但是当我们要初始化时它会很有用

List<MyObject> listOfFilesFolders = new ArrayList<MyObject>();
listOfFilesFolders.add(new MyFile());
listOfFilesFolders.add(new MyFolder());

这个“listOfFilesFolders”可以是另一个类的私有变量,它保持文件/文件夹列表的存在。

或者我们希望具有如下功能

private void SomeFunction(MyObject obj)
{

}

它可以获取从基类派生的所有对象,并根据基类的属性或功能进行操作。

于 2013-10-07T05:35:52.947 回答
0

在这里查看我的旧答案之一:

使用接口有什么好处

这是关于我的一位教授曾经告诉我们的轶事的轶事。

长话短说,当您进入更复杂的系统时,您想要这样做的原因会变得更加清晰。将规范(接口/抽象类及其契约)与实现(具体类)分离的能力是一个强大的工具,它使编写新实现变得非常容易,而无需在应用程序的其他地方更改代码。您在代码中使用规范,例如规范:

public interface Animal { ... }

您的实施:

public class Dog implements Animal { ... }

然后在代码中,尽可能使用规范:

Animal a = new Dog();
a.eat(); // All animals eat, so eat() is on the Animal interface

除非您绝对需要使用实现本身:

Dog d = new Dog();
d.bark(); // Other animals don't bark, so we need to have the Dog here

这使您的代码更干净。例如,假设我有一个方法feedAndGroom。如果我没有接口,我需要为我想要支持的每种动物创建一个新方法:

public static void feedAndGroom(Cat c) { ... }

public static void feedAndGroom(Dog d) { ... }

public static void feedAndGroom(Turtle t) { ... }

根据具体情况,每个代码块甚至可能看起来完全相同。更糟糕的是,当有人发现一种新动物时会发生什么?我们每次都必须添加一个新方法,这将导致大量的方法。所有这些重复的解决方案是围绕功能创建一个接口,然后使用一个方法:

public static void feedAndGroom(Animal a) { ... }

这将采用任何实现Animal接口的东西。所有这些方法调用都是合法的:

feedAndGroom(new Cat());
feedAndGroom(new Dog());
feedAndGroom(new Turtle());

但是,这些方法调用也是合法的:

feedAndGroom(new Hyena());
feedAndGroom(new Lion());
feedAndGroom(new Panther());

我们可能不想尝试喂养和梳理这些动物,至少不是野生动物,所以我们可以添加一个名为DomesticatedAnimalextends的新接口Animal

public interface `DomesticatedAnimal` extends `Animal` { ... }

并将我们的方法更改为:

public static void feedAndGroom(DomesticatedAnimal da) { ... }

然后代替实现AnimalDog,CatTurtle类将实现DomesticatedAnimal。例如:

public class Dog implements DomesticatedAnimal { ... }

这意味着Dog它既是一个DomesticatedAnimal,因为它直接实现它,也是一个Animal继承自DomesticatedAnimalextends Animal。其他动物 、HyenaLionPanther只是实现Animal接口。这意味着我们的新方法不会Animal像原来的那样采用任何方法,而是将其限制为特定类型的Animal对象。同时,任何为使用原始Animal接口而编写的方法仍然适用于所有涉及的对象。

于 2013-10-07T07:15:11.007 回答
0

您总是可以用对子类的引用代替基类。

换句话说,你总是可以使用更具体的东西来代替更一般的东西——所以如果你有一行代码需要一个 Canine,你可以给它发送一个 Dog 的引用。所以这行代码:

Foo ab=new Dog();

意味着您正在实例化一个新Dog对象,然后创建一个 Foo名为的引用ab并将其指向该对象。

于 2017-08-07T04:01:41.717 回答