如何使用构造函数将对象设置为现有对象?

时间:2012-03-12 13:32:02

标签: java image inheritance constructor

这是我想要使用一个简化图像加载过程的构造函数的问题。您需要做的只是指定文件路径。

是否可以通过继承执行此操作,还是需要创建新的缓冲图像对象? 这是代码的想法,使其更容易理解。

public class specialImage extends BufferedImage { 

    specialImage(String path) {
    super();
    this =  ImageIO.read(new File(Path)); // <--- how can i Do this in java. 
    }
 }

或者我应该遵循以下

 class specialImage{

    BufferedImage manipulator;

    specialImage (String path) {
       manpiulator = ImageIO.read(new File(path));
    }
  }

------------------------编辑1:----------------- --------  我想避免回来。我想创建一系列将操纵specialImage类的函数。喜欢

specialImage objectName = new specialImage(FILE_PATH);
objectName.toGrayscale();
objectName.specialTransformation();
//While still using the BufferedImage class, i.e.,
objectName.getRaster(); 

5 个答案:

答案 0 :(得分:1)

您的问题和特定问题有一般性答案。实际上,我们应该首先介绍具体问题。

你应该按照这一点做点什么。

public class SpecialImage {

  // The thing isn't a manipulator, it's a BufferedImage
  // I would suggest renaming this for ease of maintenance
  BufferedImage manipulator;

  public SpecialImage(String path) {
    manpiulator = ImageIO.read(new File(path));
  }

}

除非您知道您的子类将与父类共享相同的“行为”,否则请避免进行子类化。通过将BufferedImage作为字段放入您的类中,您使用的是一种名为“撰写”的技术,一般情况下,如果有疑问,请favor composition over inheritance

当类遵循Liskov Substitution Principle或接近英语时,继承最有效,当它们具有相同的“行为”但修改了“行为”的实现时。例如,BufferedImageVolatileImage的行为与java.awt.Image完全相同,但是一个使用可访问的缓冲区,另一个不保证缓冲区可访问性(甚至缓冲区存在) )。

您的问题的更一般的答案如下。

Object被建模为“事物”的实例,其中“事物”使用名为Class的模板建模。构建是从模板创建新“事物”的过程,或者是面向对象的术语,从Object创建Class

通过这种理解,你可以看到,为现有的“事物”构建一个“事物”充其量只是笨拙的英语,而在最坏的情况下几乎是无意义的陈述。

之一。你可能意味着什么
  • 如何构建“事物”的副本?

如果你想要一个Object的第二个副本,你需要提供一个“复制构造函数”,这是一个构造函数的通用术语,它返回第一个“东西”的第二个等价副本。

public class Car {

  private int speed;

  public Car(int mph) {
    // this is an optional keyword.  I included it for clarity.
    this.speed = mph;
  }

  // This is the copy constructor
  public Car(Car other) {
    this.speed = other.speed;
  }

  public int getSpeed() {
    return speed;
  }

}
  • 如何对现有的“东西”进行第二次引用?

您创建一个新名称,并将其指定给旧名称。旧名称(在封面下)将产生一个引用,该引用将成为新名称的新值。引用大多是隐藏的,因为名称上的所有操作都会自动“取消引用”。

 Car myCar = new Car();
 Car yourCar = myCar;  // assuming it is a shared car.

要让代码的两个部分引用相同的“东西”,你不需要使用构造函数,因为它会创建两个东西。相反,您使用两个不同的“名称”或“引用”。 Java中的引用有点像其他语言中的指针,除了它们受到许多有趣的限制。

  1. 它们不涉及实际内存位置。这允许垃圾收集来压缩内存,而不必重写未知数量的引用。内存压缩涉及将对象的数据存储从一个起始地址移动到另一个起始地址,并且通过使用“内存引用ID”而不是实际地址,需要更改的唯一物理地址是“内存引用ID”中的一个“到”物理地址“表(无法通过用户编写的程序访问此表)。

  2. 不能为他们分配任意位置。命名引用具有声明的类型,并且要分配的Object具有声明的类型。编译器和运行时环境的强类型检查保证只能将兼容类型分配给命名引用。因此,不可能将任意对象强制转换为不兼容的命名引用。

  3. 禁止数学运算,或者更准确地说,未实现数学运算。最后一个约束可以防止偏移命名引用,使其可能引用具有可能不同的非兼容类型的不同对象。

  4. 考虑到这些项目,您的原始计划将很好地运作;真正的问题是你将如何实现这些目标。如果您的“GrayScale”图像与非GrayScale图像的相同,那么使用相同的类(使用toGrayScale()方法)是一个很好的设计选择。如果您的“GrayScale”图像与非GrayScale图像的不同,则让toGrayScale()返回第二张图像是一个很好的设计选择。

    当面向对象的编程开始分崩离析时,就是你没有做出这些设计选择。您将对象视为“内存缓冲区”,并且您可以避免创建新对象并丢弃旧对象,而不是维护特定的“内存缓冲区”。除非您正在建模内存打印垫,否则这不是面向对象的设计,因此,您将在解决方案的每一步中与面向对象的环境作斗争,从而为您提供所需的输出。

    祝你好运。

答案 1 :(得分:0)

这是您使用静态工厂的地方。

public enum SpecialImage {; // Utility class.
    public static BufferedImage load(String path) {
        return ImageIO.read(new File(Path)); // <--- how can i Do this in java. 
    }
}

使用像ImageIO.read(这样的静态工厂的一个缺点是它们不能被分类。

答案 2 :(得分:0)

您仍然可以在继承BufferedImage的情况下使用第二种方法,但必须将委托方法添加到您将在specialImage类中使用的所有BufferedImage方法。

答案 3 :(得分:0)

class ImageUtil {
 public static BufferedImage loadImage(final String path) { 
   BufferedImage image = ImageIO.read(new File(path));
   return image;
 }
}

答案 4 :(得分:0)

您的第一次代码尝试是“工厂方法”,因此这将起作用:

public class SpecialImage extends BufferedImage { 
    SpecialImage(String path) {
        super();
    }

    public static SpecialImage create(String path) {
        return ImageIO.read(new File(path));
    }
}

第二次代码尝试说“组成”,所以不知道你想要做什么,我无法评论,但似乎没问题。

相关问题