Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/367.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
java中正确使用的实例_Java_Oop_Instanceof - Fatal编程技术网

java中正确使用的实例

java中正确使用的实例,java,oop,instanceof,Java,Oop,Instanceof,的实例在java中被认为是一种不好的做法。但我不知道在这种情况下如何避免。 假设我有一个抽象类ArtObject,有一些子类,比如绘画,雕刻,等等。我有一个类博物馆,其中包含ArtObject的阵列列表 例如,我想打印有关博物馆中所有绘画对象的信息 我应该这样做吗 public void printAllPaintingsInfo() { for (int i = 0; i < artObjects.size(); i++) { if (artObjects.get

的实例在java中被认为是一种不好的做法。但我不知道在这种情况下如何避免。 假设我有一个抽象类
ArtObject
,有一些子类,比如
绘画
雕刻
,等等。我有一个类
博物馆
,其中包含
ArtObject
阵列列表

例如,我想打印有关
博物馆
中所有
绘画
对象的信息

我应该这样做吗

public void printAllPaintingsInfo() {
    for (int i = 0; i < artObjects.size(); i++) {
        if (artObjects.get(i) instanceof Painting) {
            System.out.println(artObjects.get(i));
        }
    }
}
public void printAllPaintingsInfo(){
对于(int i=0;i

或者存在更好的方法?

您可以将方法
ispaint()
添加到
ArtObject
中,该方法
返回false并覆盖到
返回true在绘画中

然后你就可以写了

public void printAllPaintingsInfo() {
    for (ArtObject ao : artObjects)
        if (ao.isPainting())
            System.out.println(ao);
}
artObjects.filter(ArtObject::isPainting).forEach(System.out::println);
或者在Java8中,您可以编写

public void printAllPaintingsInfo() {
    for (ArtObject ao : artObjects)
        if (ao.isPainting())
            System.out.println(ao);
}
artObjects.filter(ArtObject::isPainting).forEach(System.out::println);

一种可能的选择是在所有
ArtObjects

// Pseudocode
class ArtObject {
  Enum artType = { Painting, Engraving }
}

class Painting implements ArtObject {
  Painting() { artType = Painting }
}

public void printAllPaintingsInfo() {
    for(int i = 0; i < artObjects.size(); i++) {
        if(artObjects.artType == Painting) {
            System.out.println(artObjects.get(i));
        }
    }
}
//伪代码
类艺术品{
枚举artType={绘画、雕刻}
}
类绘画实现ArtObject{
绘画(){artType=Painting}
}
public void printAllPaintingsInfo(){
对于(int i=0;i

另一个可能是为所有
绘画
对象保留一个单独的
集合
,除了
艺术品
集合。

我认为使用实例不会有任何问题。但是,如果您仍然不想使用它,您可以创建一个指示ArtObject类型的方法(例如type.PAINTING、type.雕刻)。

我通常在基类中定义谓词,或者添加一个显式子类名称作为 实例变量

class ArtObject {
布尔ispaint(){return(false):} 布尔isEngraving(){return(false);} }

然后在子类中,将这些方法定义为true 或者

typedef enum typeOfArt { generic, painting, engraving };
类艺术品{ typeOfArt类型=typeOfArt.generic; }

根据模型的复杂性,可以避免创建子类
如果开关(类型)造成的混乱不太严重,那就完全可以了。

如果我们这样做会怎么样

public abstract class ArtObject{

  //Classes extending this class will need to override and implement this method
  abstract public Type getType();

}


public class Painting extends ArtObject {
    /*
      Other code probably
    */

    @Override
    public Type getType(){
       return Type.Painting;
    }
}

enum Type {
   Painting, Museum;
}

public void printAllPaintingsInfo() {
    for (int i = 0; i < artObjects.size(); i++) {
        if (artObjects.get(i).getType() == Type.Painting) {
            System.out.println(artObjects.get(i));
        }
    }
}
公共抽象类ArtObject{
//扩展此类的类将需要重写并实现此方法
抽象公共类型getType();
}
公共类绘画扩展了ArtObject{
/*
可能是其他代码
*/
@凌驾
公共类型getType(){
返回式。涂装;
}
}
枚举类型{
绘画,博物馆;;
}
public void printAllPaintingsInfo(){
对于(int i=0;i
与许多通常不受欢迎的语言功能一样,通过实现某种“伪造”它们的机制,使用它们往往很容易作弊。但这并不能让事情变得更好。如果您想测试对象的类型,那么
instanceof
就是正确的选择。如果要避免这种情况,需要找到一种不需要找出对象(动态)类型的方法

避免运行时类型检查的一种流行模式是使用访客模式,该模式有效地解决了过载问题,并且动态调度机器执行脏工作。如果你的现实世界问题像你贴的博物馆例子一样简单,那么这显然是矫枉过正。不管怎么说,这是可以做到的

在本例中,假设我们有
Painting
s和
Drawings
,它们都是从
ArtObject
派生的。我们定义了一个抽象访问者类型,它对每个
ArtObject
都有一个方法。或者,您只能专门处理一些问题,并使用回退“访问任何内容”方法

public abstract class ArtVisitor {

    public void visit(final Painting painting) {
    }

    public void visit(final Drawing drawing) {
    }

    // public void visit(final ArtObject anything) {
    // }
}
我使用了一个抽象类而不是接口,因此我可以使用
visit
方法的空默认实现

ArtObject
接口(或抽象类)中,我们需要添加一个抽象
takeVisitor
方法

public abstract class ArtObject {

    private final String name;

    protected ArtObject(final String name) {
        this.name = name;
    }

    public abstract void takeVisitor(ArtVisitor visitor);

    @Override
    public final String toString() {
        return String.format("%s (%s)",
                             this.name,
                             this.getClass().getCanonicalName());
    }
}
不幸的是,我们无法实现
ArtObject.takeVisitor
,因为
这个
指针将具有静态类型
ArtVisitor
,这将要求我们进行类型内省,这正是我们想要避免的。相反,我们必须——这是访问者模式最丑陋的地方——在我们的每个类中覆盖它

(如果我们添加了回退
ArtVisitor.visit(ArtObject)
方法,我们可以实现一个通用的
takeVisitor
方法,但是我们仍然必须在派生类中重写它,以便根据
this
指针的类型进行重载解析。在大多数情况下,这会增加更多的混乱(和潜在的缺陷)而不是好处。)

现在我们可以直接建造博物馆了

import java.util.List;
import java.util.ArrayList;

public final class Museum {

    private final List<ArtObject> artworks;

    public Museum() {
        this.artworks = new ArrayList<ArtObject>();
        artworks.add(new Painting("Mona Lisa"));
        artworks.add(new Drawing("Madame Palmyre with Her Dog"));
        artworks.add(new Painting("The Night Watch"));
    }

    public void printAllWorks() {
        for (final ArtObject work : this.artworks) {
            System.out.println(work);
        }
    }

    public void printAllPaintings() {
        final ArtVisitor paintingsPrinter = new ArtVisitor() {

            @Override
            public void visit(final Painting painting) {
                System.out.println(painting);
                // Note: We don't need any unsafe downcast here!
                painting.aMethodOnlyPaintingsHave();
            }
        };
        for (final ArtObject work : this.artworks) {
            work.takeVisitor(paintingsPrinter);
        }
    }

    public static void main(final String[] args) {
        final Museum myMuseum = new Museum();
        System.out.println("All ArtObjects:\n");
        myMuseum.printAllWorks();
        System.out.println("\n\nAll Paintings:\n");
        myMuseum.printAllPaintings();
    }
}

什么是artObjects?列表、数组或Iterable的某个实例?@KumarAbhinav:为什么在使用
实例的过程中这会很重要呢。但对于这种情况来说,这可能是过火了。谢谢你的回答,我学到了很多解决这个问题的有趣方法。但我认为在这种情况下,最有效的方法是使用instanceof:)为每个对象添加一个字段,这似乎效率很低。如果你有一个子类型的
绘画
,这是一幅
肖像画
,我认为将
绘画
添加到
艺术对象
是相当低效的。而且不知何故,它忽略了为什么首先应该避免
实例的问题。类型字段在CW中很有用