我正在尝试引入一个Shape
类作为类Circle
和Rectangle
的父接口。我必须实现getName()
方法,该方法将为Circle
对象返回Circle
,为Rectangle
对象返回Rectangle
。此外,我必须在Circle
和Rectangle
类中重写toString()
方法。toString
方法将调用getName()
方法,并将生成一个表示对象的字符串,如下所示:
- 半径为 2 的
Circle
表示为"Circle(2)"
- 宽度为 2 且高度为 10 的
Rectangle
表示为"Rectangle(2, 10)"
。
另外,我无法修改类Shape
,Rectangle
,Circle
或Main
,您可以在下面找到代码。我不确定如何做到这一点。有人可以帮我吗?
这是我到目前为止所做的:
形状.java
public interface Shape {
String getName();
double getPerimeter();
double getArea();
}
矩形.java
public class Rectangle {
private double width, height;
public Rectangle(double width, double height) {
this.width = width;
this.height = height;
}
public double getPerimeter() {
return 2 * (this.width + this.height);
}
public double getArea() {
return this.width * this.height;
}
}
圈子.java
public class Circle{
private double radius;
public Circle(double radius) {
this.radius = radius;
}
public double getPerimeter() {
return 2 * Math.PI * this.radius;
}
public double getArea() {
throw new RuntimeException("Oops, I don't know how to calculate this :(");
}
}
问题.aj
public aspect Question {
declare parents: Rectangle implements Shape;
declare parents: Circle implements Shape;
public String Rectangle.getName(){
return "Rectangle";
}
public String Circle.getName(){
return "Circle";
}
public String Rectangle.toString(){
return Rectangle.getName()+"(" + this.width +", " + this.height +")";
}
public String Circle.toString(){
return Circle.getName() + "(" + this.radius + ")";
}
}
主.java
public class Main {
public static void main(String[] args) {
try {
Shape s;
s = (Shape) new Rectangle(2, 10);
System.out.println("The area of " + s + " is " + s.getArea());
s = (Shape) new Rectangle(-2, 10);
System.out.println("The perimeter of " + s + " is " + s.getPerimeter());
s = (Shape) new Circle(-2);
System.out.println("The perimeter of " + s + " is " + s.getPerimeter());
s = (Shape) new Circle(2);
System.out.println("The area of " + s + " is " + s.getArea());
}
catch(Exception e) {
System.out.println("Error: " + e.getMessage());
}
}
}
我正在尝试引入一个 Shape 类作为 类 圆形和矩形
为此,您需要使用类型间声明AspectJ静态横切功能,该功能允许更改类的结构,即添加新方法,使类实现接口等。您正确完成的操作:
declare parents: Rectangle implements Shape;
declare parents: Circle implements Shape;
我必须实现 getName() 方法,该方法将返回 "圆" 圆形对象和矩形对象的"矩形"。
你也做对了:
public String Rectangle.getName(){
return "Rectangle";
}
public String Circle.getName(){
return "Circle";
}
另外,我必须在 Circle 和 Rectangle>类中重写 toString() 方法。
你也做对了:
public String Rectangle.toString(){ (...)}
public String Circle.toString(){ (...)}
toString 方法将调用 getName() 方法并将生成 表示对象的字符串,如下所示: 半径为 2 的圆 表示为"Circle(2)"矩形,宽度为 2,高度为 10 表示为"矩形(2, 10)"。
这一步你做错了:
public String Rectangle.toString(){
return Rectangle.getName()+"(" + this.width +", " + this.height +")";
}
public String Circle.toString(){
return Circle.getName() + "(" + this.radius + ")";
}
你有两个问题,
方法
getName()
不是静态的,因此更改两者Rectangle.getName()
和Circle.getName()
this.getName();
字段
width
、height
和radius
是私有的。因此,您不能简单地从这样的方面访问它们。从源头:
在方面编写的代码受与 引用类或方面的成员时的 Java 代码。所以,对于 例如,在某个方面编写的代码可能不引用具有 默认(受包保护)可见性,除非在 中定义了方面 相同的包。
虽然这些限制适用于许多方面,但可能存在 建议或类型间成员需要访问的某些方面 其他类型的私有或受保护资源。为了允许这一点,方面 可以宣布特权。特权方面的代码可以访问 所有成员,甚至是私人成员。
要解决此问题,您(至少)有 3 个选项:
- 公开这些字段;
- 使方面
Question
特权; - 为这些私人领域制作吸气剂。
从OOP
封装的角度来看,第三种选择是最好的。看起来像这样:
在类Rectangle
添加width
和height
字段的 getter:
public double getWidth() {return this.width;}
public double getHeight() {return this.height;}
并在类中添加Circle
radius
字段的 getter:
public double getRadius() {return this.radius;}
最后,相应地调整方面Question
:
public String Rectangle.toString(){
return this.getName()+"(" + this.getWidth() +", " + this.getHeight() +")";
}
public String Circle.toString(){
return this.getName() + "(" + this.getRadius()+ ")";
}
另外,我无法修改形状,矩形,圆形或主类, 您将在下面找到代码。
好吧,这不包括方法1)(无论如何都很糟糕)和3)(作为最好的IMO)。
因此,您可以使方面Question
特权:
privileged public aspect Question
我同意一些作者的相同观点:
- J. D. Gradecki和N. Lesiecki.在《掌握AspectJ:Java中面向方面编程》一书中。
- R. Laddad. 在《AspectJ in Action: Enterprise AOP with Spring Applications》一书中。
应尽可能避免特权方面,因为它们在方面和类之间增加了 an
固有依赖关系,并且它们规避了应用于该目标类的可见性规则。