我想介绍一个Shape
类作为类父接口Circle
和Rectangle
。我必须实现getName()
将Circle
为该Circle
对象和Rectangle
该Rectangle
对象返回的方法。另外,我必须toString()
在Circle
和Rectangle
类中都覆盖该方法。这些toString
方法将调用该getName()
方法,并将生成一个表示对象的字符串,如下所示:
Circle
半径为2的表示为 "Circle(2)"
Rectangle
宽度为2且高度为10的表示为"Rectangle(2, 10)"
。此外,我不能修改的类Shape
,Rectangle
,Circle
或者Main
,为此你会发现下面的代码。我不确定如何执行此操作。有人可以帮帮我吗?
到目前为止,这是我所做的:
Shape.java
public interface Shape {
String getName();
double getPerimeter();
double getArea();
}
Rectangle.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;
}
}
Circle.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 :(");
}
}
问题
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 + ")";
}
}
Main.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类作为Circle和Rectangle类的父接口引入
为此,你需要使用类型间声明,这是AspectJ静态横切功能,该功能允许更改类的结构,即添加新方法,使类实现接口等。你已正确完成以下操作:
declare parents: Rectangle implements Shape;
declare parents: Circle implements Shape;
我必须实现getName()方法,该方法将为Circle对象返回“ Circle”,为Rectangle对象返回“ Rectangle”。
你还正确地做到了:
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的矩形表示为“ Rectangle( 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
字段添加吸气剂:
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()+ ")";
}
另外,我无法修改Shape,Rectangle,Circle或Main类,你将在其中找到以下代码。
Okey,这不包括方法1)(无论如何还是不好的)和方法3)(这是最好的IMO)。
因此,你将使该方面具有Question
特权:
privileged public aspect Question
我与一些作者有相同的看法:
该特权方面应避免尽可能多的,因为它们增加一个
方面和类之间的内在相关性,他们绕过能见度规则,应用在目标类。