如何添加方法并拦截来自不同类的私有字段
Posted
技术标签:
【中文标题】如何添加方法并拦截来自不同类的私有字段【英文标题】:How to add method and intercept private fields from a different class 【发布时间】:2020-12-07 04:02:52 【问题描述】:我正在尝试引入Shape
类作为Circle
和Rectangle
类的父接口。我必须实现getName()
方法,该方法将为Circle
对象返回Circle
,为Rectangle
对象返回Rectangle
。此外,我必须在 Circle
和 Rectangle
类中覆盖 toString()
方法。 toString
方法将调用getName()
方法并生成一个表示对象的字符串,如下所示:
Circle
表示为 "Circle(2)"
Rectangle
宽度为 2,高度为 10 表示为 "Rectangle(2, 10)"
。
另外,我无法修改 Shape
、Rectangle
、Circle
或 Main
类,您将在下面找到代码。我不确定如何做到这一点。有人可以帮帮我吗?
这是我到目前为止所做的:
Shape.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;
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 :(");
问题.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());
【问题讨论】:
【参考方案1】:我正在尝试引入一个 Shape 类作为父接口 类圆形和矩形
为此,您需要使用 inter-type declarations 一个 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 表示为“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
字段是私有。因此,您不能简单地从这样的方面访问它们。来自source:
方面编写的代码受制于相同的访问控制规则 引用类或方面成员时的 Java 代码。 因此,对于 例如,在一个方面编写的代码可能不会引用具有 默认(包保护)可见性,除非方面在 同一个包。
虽然这些限制适用于许多方面,可能有 建议或跨类型成员需要访问的某些方面 其他类型的私有或受保护资源。为了允许这一点,方面 可以声明特权。特权方面的代码可以访问 所有成员,甚至私人成员。
要解决这个问题,您有(至少)3 个选项:
-
公开这些字段;
使方面
Question
特权;
为这些私有字段创建 getter。
从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()+ ")";
另外,我无法修改 Shape、Rectangle、Circle 或 Main 类, 您将在下面找到代码。
好吧,这不包括方法 1)(无论如何都很糟糕)和 3)(这是最好的 IMO)。
因此,您只能将方面设置为Question
特权:
privileged public aspect Question
我同意一些作者的相同观点:
J. D. Gradecki 和 N. Lesiecki。 Mastering AspectJ: Aspect-Oriented Programming in Java 一书中。 R.拉达德。在 AspectJ in Action: Enterprise AOP with Spring Applications 一书中。应尽可能避免特权方面,因为它们增加了 方面和类之间的内在依赖关系,并且它们规避应用于该目标类的可见性规则。
【讨论】:
以上是关于如何添加方法并拦截来自不同类的私有字段的主要内容,如果未能解决你的问题,请参考以下文章