我们如何"使用"一个类(Class-1)在另一个类(Class-2)中,因为Class-1只包含属性和相应的get函数和set函数,而Class-2具有所有的操作函数(以前属于Class-1) )并使用Class-1属性?
最终目标是在一个单独的文件中创建一个独立的Class-1 ---只包含属性,setter和getter以及一个包含所有方法的Class-2 ---一级。假设Class 2导入类1,并且只在主[或调用]函数中创建了Class-2对象。
一种方法是在Class-2中声明Class-1的对象,然后使用该对象的属性和get-set函数,但正如我在https://www.artima.com/objectsandjava/webuscript/ClassesObjects1.html中读到的那样,该方法是" has-a"上课,不是"使用-a"类。
那么如何实施"使用-a"类? 有关更清晰的信息,请参阅https://www.artima.com/objectsandjava/webuscript/ClassesObjects1.html。
答案 0 :(得分:0)
也许这是思考它的一种方式。 Square是Rectangle的子元素,Rectangle是Shape的子元素。在这种情况下,以下内容将为您提供有关架构的概念。请注意,虽然我已经将Shape
称为抽象类,但由于它没有实现任何函数,因此最好将其用作接口。
更重要的是,以这种方式思考。我们正在考虑做方形/矩形。如果形状是圆形怎么办?我们真的可以依赖于Shape中的area()函数的实现吗?
[请注意,这不是编译的,我有一段时间没有编写Java。所以,请原谅语法错误。我希望得到我的观点。]
所以也许,这是我们的Shape看起来像(?)
public abstract class interface Shape
public interface Shape {
public abstract double area();
public abstract double perimeter();
}
Circle可以做这样的事情......
/* You might need to import the Math.. thing here
Note: Circle implements Shape, not extends,
since Shape is an interface. */
public class Circle implements Shape {
private final double rad;
private final double PI = Math.PI;
public Circle(double rad) {
this.rad = rad;
}
public double area() {
return PI * Math.pow(rad, 2);
}
public double perimeter() {
return 2 * PI * rad;
}
}
现在,让我们得到Rectangle
。
public class Rectangle implements Shape {
private final double WIDTH, HEIGHT;
public Rectangle(double width, double height) {
this.WIDTH = width;
this.HEIGHT = height;
}
public double area() {
return this.WIDTH * this.HEIGHT;
}
public double perimeter() {
return 2 * (this.WIDTH + this.HEIGHT);
}
}
如果您考虑一下,Square
是Rectangle
的专门案例。 (可能)在Rectangle
中使用一些Square
属性是有意义的。
public class Square extends Rectangle {
// already have width, height in Rectangle
public Square(double side) {
super(side, side);
}
// note that you do not need area
// and perimeter any more since Rectangle
// has them implemented
/* You could of course do something like this..
public double area() {
return super.area();
}
*/
}
现在,结束。 "has-a" vs "use-a"
。如果Square
没有使用Rectangle
内容,那么它现在不需要延伸,是吗?也许实施Shape
就足够了。说,Square
已在其中定义了字段side
。那么,在这种情况下,是否值得拥有Rectangle
?我想这会给你一个想法。其余部分完全取决于您的实施。如果你有很多这样的事情发生,也许可以考虑重新设计。我认为这种罕见的事情可以原谅。你将是最好的法官。
答案 1 :(得分:0)
我们如何"使用"一个类(Class-1)在另一个类(Class-2)中,因为Class-1只包含属性和相应的get函数和set函数,而Class-2具有所有的操作函数(以前属于Class-1) )并使用Class-1属性?
如果Class-2没有拥有任何Class-1,那么它在任何给定点上使用的唯一方法是它是否创建一个,或者如果它有一个提供给它。然而,它获得一个实例,它可以查询和操作该实例的状态,并且它可以将该实例传递给其他对象。没有其他用途是可能的,因为这是任何人都可以使用Class-1实例的全部范围。
当你说"在主[或调用]函数"中只创建了Class-2对象时,我认为你是指任何调用Class-2方法的人都没有任何类 - 提供1个实例。特别是,我假设您没有在直接创建Class-1实例的用户和间接创建一个实例的用户之间绘制一条虚线,例如通过Class-2。这种区别毫无意义。如果Class-2代表其用户创建了Class-1的实例并将其提供给用户,则用户已经有效地创建了它们。如果用户可以通过任何方式获取Class-1实例 ,那么这些方法的细节在问题的抽象层次上是无关紧要的。
只留下Class-2"使用"它根据需要自己创建的第1类实例,它仅通过局部变量和/或方法参数引用(因为它不会"具有"任何Class-1),并且它不允许是暴露给它的用户。这当然是可能的,但它的实用性有限。如果该设计有效,则可以完全删除Class-1,替换为Class-2的局部变量和方法参数。然而,考虑到原始的单级设计确实具有状态,这样的设计似乎不太可能起作用。不过,这是可能的。
另请注意,如果Class-2不拥有特定的Class-1实例,那么它唯一可以限制为仅使用的特定Class-1 instance是指如果使用仅限于在Class-2实例生命周期中只能发生一次的某些事件,例如其初始化。否则,它不是"使用 a "关系,而是使用关系。
由于原始设计同时具有状态和行为,因此似乎不可能简单地省略状态部分。在这种情况下,Class-2用户不创建任何Class-1实例的约束似乎是错误的。你也许可以通过创建另一个保持与Class-1相同状态的类来解决它,但那是荒谬的。为什么要创建一个新课程,因为已经有一个非常好的课程?如果您只是想避免Class-1直接由Class-2之外的类实例化,那么允许Class-2为其用户提供Class-1的实例。由于用户可以获取实例,因此可以将它们作为方法参数反馈给Class-2。这允许Class-2使用Class-1而不拥有自己的Class-1。例如,
public class State {
private int x;
State(int x) { // package-private
this.x = x;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
}
public class Behavior {
// Uses State, but is not a State and does not have a State
public State doSomethingThatYieldsState(String s) {
try {
return new State(Integer.parseInt(s));
} catch (NumberFormatException nfe) {
return null;
}
}
public int doSomethingWithState(State s, int y) {
return y + s.getX();
}
public void doSomethingToState(State s) {
s.setX(s.getX() + 1);
}
}