如何添加方法并拦截来自不同 class 的私有字段
How to add method and intercept private fields from a different class
我正在尝试引入 Shape
class 作为 classes Circle
和 Rectangle
的父界面。我必须实现 getName()
方法,该方法将为 Circle
对象实现 return Circle
,为 Rectangle
对象实现 Rectangle
。此外,我必须在 Circle
和 Rectangle
class 中覆盖 toString()
方法。 toString
方法将调用 getName()
方法并生成表示对象的字符串,如下所示:
半径为 2 的 Circle
表示为 "Circle(2)"
Rectangle
宽度为 2 & 高度为 10 表示为 "Rectangle(2, 10)"
.
此外,我无法修改 classes 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 :(");
}
}
Question.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 + ")";
}
}
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());
}
}
}
I am trying to introduce a Shape class as a parent interface for the
classes Circle and Rectangle
为此,您需要使用 inter-type declarations AspectJ 静态横切 功能,该功能允许更改 class,即添加新方法,使class实现接口等。你做对了:
declare parents: Rectangle implements Shape;
declare parents: Circle implements Shape;
I have to implement getName() method that will return "Circle" for the
Circle object and "Rectangle" for the Rectangle object.
你也做对了:
public String Rectangle.getName(){
return "Rectangle";
}
public String Circle.getName(){
return "Circle";
}
Also, I have to override the toString() method in both the Circle and Rectangle > classes.
你也做对了:
public String Rectangle.toString(){ (...)}
public String Circle.toString(){ (...)}
The toString methods will call the getName() method and will generate
a string representing the object as follows: Circle with radius of 2
is represented as "Circle(2)" Rectangle with width of 2 & height of 10
is represented as "Rectangle(2, 10)".
这一步你做错了:
public String Rectangle.toString(){
return Rectangle.getName()+"(" + this.width +", " + this.height +")";
}
public String Circle.toString(){
return Circle.getName() + "(" + this.radius + ")";
}
你有两个问题,
方法 getName()
不是 static,因此两者都要更改
Rectangle.getName()
和 Circle.getName()
到 this.getName();
字段 width
、height
和 radius
是 private。因此,您不能简单地从那样的方面访问它们。来自 source:
Code written in aspects is subject to the same access control rules as
Java code when referring to members of classes or aspects. So, for
example, code written in an aspect may not refer to members with
default (package-protected) visibility unless the aspect is defined in
the same package.
While these restrictions are suitable for many aspects, there may be
some aspects in which advice or inter-type members needs to access
private or protected resources of other types. To allow this, aspects
may be declared privileged. Code in priviliged aspects has access to
all members, even private ones.
要解决这个问题,你有(至少)3个选项:
- 将这些字段设置为 public;
- 使方面
Question
特权;
- 为这些私有字段创建 getters。
从OOP
封装的角度来看,第三种选择是最好的。看起来像这样:
向 class Rectangle
添加 width
和 height
字段的 getter:
public double getWidth() {return this.width;}
public double getHeight() {return this.height;}
并在 class 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()+ ")";
}
Also, I cannot modify the classes Shape, Rectangle, Circle or Main,
for which you will find the codes bellow.
好吧,这不包括方法 1)(无论如何都不好)和 3)(这是最好的 IMO)。
因此,您只剩下 Question
特权:
privileged public aspect Question
我同意一些作者的观点:
- J。 D. Gradecki 和 N. Lesiecki。在 Mastering AspectJ: Aspect-Oriented Programming 一书中 Java.
- R。拉达。在 AspectJ in Action:Enterprise AOP with Spring Applications.
一书中
应尽可能避免 特权 方面,因为它们添加了
方面和 classes 之间的内在依赖性,它们 规避 应用于该目标的可见性规则 class.
我正在尝试引入 Shape
class 作为 classes Circle
和 Rectangle
的父界面。我必须实现 getName()
方法,该方法将为 Circle
对象实现 return Circle
,为 Rectangle
对象实现 Rectangle
。此外,我必须在 Circle
和 Rectangle
class 中覆盖 toString()
方法。 toString
方法将调用 getName()
方法并生成表示对象的字符串,如下所示:
-
半径为 2 的
Circle
表示为"Circle(2)"
Rectangle
宽度为 2 & 高度为 10 表示为"Rectangle(2, 10)"
.
此外,我无法修改 classes 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 :(");
}
}
Question.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 + ")";
}
}
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());
}
}
}
I am trying to introduce a Shape class as a parent interface for the classes Circle and Rectangle
为此,您需要使用 inter-type declarations AspectJ 静态横切 功能,该功能允许更改 class,即添加新方法,使class实现接口等。你做对了:
declare parents: Rectangle implements Shape;
declare parents: Circle implements Shape;
I have to implement getName() method that will return "Circle" for the Circle object and "Rectangle" for the Rectangle object.
你也做对了:
public String Rectangle.getName(){
return "Rectangle";
}
public String Circle.getName(){
return "Circle";
}
Also, I have to override the toString() method in both the Circle and Rectangle > classes.
你也做对了:
public String Rectangle.toString(){ (...)}
public String Circle.toString(){ (...)}
The toString methods will call the getName() method and will generate a string representing the object as follows: Circle with radius of 2 is represented as "Circle(2)" Rectangle with width of 2 & height of 10 is represented as "Rectangle(2, 10)".
这一步你做错了:
public String Rectangle.toString(){
return Rectangle.getName()+"(" + this.width +", " + this.height +")";
}
public String Circle.toString(){
return Circle.getName() + "(" + this.radius + ")";
}
你有两个问题,
方法
getName()
不是 static,因此两者都要更改Rectangle.getName()
和Circle.getName()
到this.getName();
字段
width
、height
和radius
是 private。因此,您不能简单地从那样的方面访问它们。来自 source:
Code written in aspects is subject to the same access control rules as Java code when referring to members of classes or aspects. So, for example, code written in an aspect may not refer to members with default (package-protected) visibility unless the aspect is defined in the same package.
While these restrictions are suitable for many aspects, there may be some aspects in which advice or inter-type members needs to access private or protected resources of other types. To allow this, aspects may be declared privileged. Code in priviliged aspects has access to all members, even private ones.
要解决这个问题,你有(至少)3个选项:
- 将这些字段设置为 public;
- 使方面
Question
特权; - 为这些私有字段创建 getters。
从OOP
封装的角度来看,第三种选择是最好的。看起来像这样:
向 class Rectangle
添加 width
和 height
字段的 getter:
public double getWidth() {return this.width;}
public double getHeight() {return this.height;}
并在 class 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()+ ")";
}
Also, I cannot modify the classes Shape, Rectangle, Circle or Main, for which you will find the codes bellow.
好吧,这不包括方法 1)(无论如何都不好)和 3)(这是最好的 IMO)。
因此,您只剩下 Question
特权:
privileged public aspect Question
我同意一些作者的观点:
- J。 D. Gradecki 和 N. Lesiecki。在 Mastering AspectJ: Aspect-Oriented Programming 一书中 Java.
- R。拉达。在 AspectJ in Action:Enterprise AOP with Spring Applications. 一书中
应尽可能避免 特权 方面,因为它们添加了
方面和 classes 之间的内在依赖性,它们 规避 应用于该目标的可见性规则 class.