首页 \ 问答 \ 调用方面声明的方法(Calling methods declared in an aspect)

调用方面声明的方法(Calling methods declared in an aspect)

此页面显示了如何向现有类添加方法,然后演示如何在调用这些其他方法的方面内声明方法。

这是该页面的代码:

aspect PointObserving {
    private Vector Point.observers = new Vector();

    public static void addObserver(Point p, Screen s) {
        p.observers.add(s);
    }
    public static void removeObserver(Point p, Screen s) {
        p.observers.remove(s);
    }

    pointcut changes(Point p): target(p) && call(void Point.set*(int));

    after(Point p): changes(p) {
        Iterator iter = p.observers.iterator();
        while ( iter.hasNext() ) {
            updateObserver(p, (Screen)iter.next());
        }
    }

    static void updateObserver(Point p, Screen s) {
        s.display(p);
    }
}

我试图在相同的设置(观察者模式)中重用此模式,但我希望能够从我的Java代码中的任何位置添加观察者。 因此,在该页面上显示的示例中,我想从我的包中的另一个类做这样的事情:

Point p = new Point(120, 230);
Screen s = getScreen();
PointObserving.addObserver(p, s);

但是,“方面”PointObserving对我的Java类是不可见的(尽管我已将其声明为public)。


This page shows how one can add methods to existing classes and then shows how to declare methods inside the aspect that call those additional methods.

This is the code from that page:

aspect PointObserving {
    private Vector Point.observers = new Vector();

    public static void addObserver(Point p, Screen s) {
        p.observers.add(s);
    }
    public static void removeObserver(Point p, Screen s) {
        p.observers.remove(s);
    }

    pointcut changes(Point p): target(p) && call(void Point.set*(int));

    after(Point p): changes(p) {
        Iterator iter = p.observers.iterator();
        while ( iter.hasNext() ) {
            updateObserver(p, (Screen)iter.next());
        }
    }

    static void updateObserver(Point p, Screen s) {
        s.display(p);
    }
}

I am trying to reuse this pattern in the same setting (observer pattern) but I want to be able to add observers from anywhere in my Java code. Thus, in the example shown on that page, I want to do something like this from another class in my package:

Point p = new Point(120, 230);
Screen s = getScreen();
PointObserving.addObserver(p, s);

However, the "aspect" PointObserving is not visible to my Java classes (though I have declared it public).


原文:https://stackoverflow.com/questions/15846723
更新时间:2024-01-26 22:01

最满意答案

在这一点上,我想到的是,带有@property的实例变量必须在类的init方法中没有自己的情况下使用,并在dealloc中释放它们

这与事实完全相反。 @property只是让变量在课堂外公开。 如果您有另一个类调用该对象,它将查找头文件(.h文件),如果它没有看到该名称的变量,它将在编译过程中发出警告,并在运行时发生错误。 当使用合成属性(顺便说一句,你的合成可以全部在一行上,但是并不重要,例如:@synthesize varA,varB,varC;),使用self会自动保留并保留一个保留计数。

- (id) initClass:(NSString *)desc{ //Note the "-" instead of the "+" here, this is an instance method, not a class method
    self = [super init];

    if( self ){
        [self setVarA:[NSString stringWithString:desc]];
        [self setVarB:[OtherClass initClassWithAutorelease:@"a description"]];

        [varB aMethod:@"something"];
    }

    return self;
}

在其他方法中,对所有情况使用自我都很方便。

非常不真实。 如果有的话,这会增加对调用堆栈的另一个调用,并使执行速度变慢(通过一次操作,但仍然比需要的多一次)。 考虑这个例子:

[[self varA] doStuff:@"OMG"];

[varA doStuff:@"OMG"];

第二个将只访问一个指针,第一个指针必须访问2个指针才能得到相同的结果。

首先,我想如果我在init方法中使用self.varA =,那么retain计数器会增加,所以我必须在dealloc方法中释放它,即使对象尚未使用alloc,copy或new创建。

不真实的。 该类处理第一个保留,因此,它也处理发布。 当你的课堂被释放时,它会将一个发布版本发布到它保留的所有东西上。 如果你在你的dealloc中发布一个版本,这实际上会将其保留计数减少到-1,并产生一个内存错误。 如果你使用self.varA = someObject设置属性,那么当你的类被处理时它会给它一个释放。 如果你做了self.varA = [someObject retain],那么你将不得不在dealloc中发布一个版本。

或者我可以在init中只使用varA =,我不需要发布。

真的,你不需要做一个释放,因为你没有保留。 但是如果其他东西将这个对象的保留计数降低到0,那么在你的类中没有任何东西强制对象保持活动状态,并且它将被释放,并且如果引用它,内存错误。

对于其他类方法,最好使用setter / getter,这样我就可以使用self.varA =,... appendString:self.varA ...或... = self.varA没有问题。 这一切是正确的吗?

不,看看上面的原因。 如果要更改对象的实例,只能使用[self setVarA:newValue],合成将处理其余部分。 否则,只需使用[varAval]来获取您需要的数据。

第二个疑问是,在内存管理和简单性方面最好的方法是在init方法中为实例变量分配一个对象,使用或不使用autorelease? 如果我给它分配一个没有autorelease的,我将不得不释放它,但如果我使用autorelease变量可以在我想要之前释放(如autoreleased self.varB = [OtherClass ...将在dealloc方法中使用,每当MyClass发布)。

如果你在init中创建一个新对象,autorelease它。 如果你只做一个常规的alloc初始化,你将不得不在你的dealloc中释放它。 变量在您想要之前不会被释放,因为您通过属性对其进行了保留。 EX

-(id) init {
   self = [super init];

   if(self) {
       [self setVarA:[[[NSString alloc] init] autorelease]]; //Sets a new instance of NSString, autoreleased
   }

   return self;
}

这是正确的,你不需要在你的dealloc中做任何事情。 您正在创建一个保留计数为2的对象(一个用于您在此处执行的分配,另一个用于合成设置类中的值时执行的保留)。 现在,如果它自动释放,它的留存率只会减少1,并且您的财产中仍然有留存,所以它不会在您的课程发布前发布

-(id) init {
   self = [super init];

   if(self) {
       [self setVarA:[[NSString alloc] init]]; //Sets a new instance of NSString
   }

   return self;
}

再次,您创建一个保留计数为2的对象。您需要在dealloc中执行一个[varA release]以将保留计数降低到足以让您的类在发布时释放。

第三,即使我不在init方法中使用它们,我是否必须释放所有实例变量,但是我可以在同一类的其他方法中使用它们(读/写)? (就像方法1中的varC或未使用的varD一样)。

不,你不想发送释放到释放的对象。 在我看来,你真的不应该使用dealloc,但是如果你决定要确定,那么最糟糕的情况是检查对象是否为null,如果不是,则释放它

if(varD != null)
   [[self varD] release];

第四,如果我在initClass和dealloc方法中做得很好,我是否需要在方法1中分配新值之后照顾varA? 换句话说,这会产生内存泄漏吗?

NSString没有内存泄漏。 这个方法返回一个自动释放对象。 当您为[self varA]指定新值时,它将释放旧对象并保留新对象。

第五,如果我声明autorelease这个类像一个实例变量在ViewController(MyClass * c; ... c = [[[MyClass alloc] initClass:@“description”] autorelease];),我设置了@property,如果我用c = ...而不是self.c = ...来使用它,我必须做一个发布吗? 据我所知,行为与我的例子相同,所以我应该在viewDidLoad或viewWillAppear中使用setter / get方法,并在dealloc中将其释放,而不会自行释放它。

两种情况下都不需要发布。 这个alloc增加了释放次数1,autorelease会将它减少到0.如果你做了self.c,那么它会将它增加到2,并且当你的班级减少到0(从autorelease减少一个,从属性减少一个)发行了。 你不需要在dealloc中做任何事情。

第六个也是最后一个,对于一个实例变量是varA与self-> varA相同。

是的,他们指向内存中的相同位置。


At this point what I have in mind is that the instance variables with @property have to be use without self in the init method of the class and release them without self in the dealloc

This is completely the opposite of what is true. @property just makes the variable public outside of the class. If you have another class call that object, it will look in the header file (.h file), if it doesn't see a variable by that name, it will throw a warning during compile, and an error during runtime. When using properties with synthesize (btw, your synthesize can be all on one line, doesn't really matter though, ex: @synthesize varA, varB, varC;), using self automatically retains and keeps a retain count.

- (id) initClass:(NSString *)desc{ //Note the "-" instead of the "+" here, this is an instance method, not a class method
    self = [super init];

    if( self ){
        [self setVarA:[NSString stringWithString:desc]];
        [self setVarB:[OtherClass initClassWithAutorelease:@"a description"]];

        [varB aMethod:@"something"];
    }

    return self;
}

in other methods it is convinient to use self for all cases.

Very untrue as well. If anything, this adds another call to the call stack and makes the execution slower (by one operation, but still, one more than needed). Consider this example:

[[self varA] doStuff:@"OMG"];

versus

[varA doStuff:@"OMG"];

The 2nd one will only access one pointer, where as the first one will have to access 2 pointers to get to the same result.

First, I suppose that if I use self.varA= in the init method the retain counter increase so I have to release it in the dealloc method, even if the object has not been created with alloc, copy or new.

Untrue. The class handles the first retain, and because of this, it handles a release as well. When your class is released, it sends a release to everything it has a retain on. If you do a release in your dealloc, this will actually decrease its retain count to -1 and create a memory error. If you set the property with self.varA = someObject, then it will give it a release when your class is dealloced. If you did self.varA = [someObject retain], then you would have to do a release in the dealloc.

Or I can use only varA= in the init and I will not need to do a release.

Kinda true, you would not need to do a release because you did not do a retain. But if something else lowers the retain count to 0 on this object, there is nothing in your class that forces the object to stay alive, and it will be freed, and if you reference it, memory error.

For other class methods it's better to use the setter/getter so I can use self.varA=, ... appendString:self.varA ... or ...=self.varA without problem. Is all this correct?

No, see why above. Only use [self setVarA:newValue] if you are changing the instance of the object, the synthesize will handle the rest. Otherwise just use [varA value] to get what ever data you need.

Second doubt, what is best in terms of memory management and simplicity, to assign to an instance variable an object in the init method with or without autorelease? If I assign to it one without autorelease I will have to dealloc it but if I use autorelease the variable could be released before I want (like the autoreleased self.varB = [OtherClass... that will be used in the dealloc method whenever the MyClass is released).

If you are creating a new object in init, autorelease it. You will have to release it in your dealloc if you do just a regular alloc init. The variable will not be released before you want it because of the retain you do on it through the property. EX

-(id) init {
   self = [super init];

   if(self) {
       [self setVarA:[[[NSString alloc] init] autorelease]]; //Sets a new instance of NSString, autoreleased
   }

   return self;
}

This is correct, you do not need to do anything in your dealloc. You are creating an object with a retain count of 2 (one for the alloc you did here, and 1 for the retain you do when the synthesize sets the value in your class). Now, if it autoreleases, its retain will only go down by 1, and you will still have the retain from your property, so it will not release before your class releases

-(id) init {
   self = [super init];

   if(self) {
       [self setVarA:[[NSString alloc] init]]; //Sets a new instance of NSString
   }

   return self;
}

Again, you create an object with a retain count of 2. You will need to do a [varA release] in the dealloc to knock the retain count down enough for it to be released when your class is released.

Third, do I have to dealloc all my instance variables even if I don't use them in the init method but I could use them (read/write) in other methods of the same class? (Like varC in method1 or varD that is not used).

No, you do not want to send releases to freed objects. You really should never use a dealloc in my opinion, but if you decide you want to for sure, then the worst case is to check to see if the object is null, and if its not, then release it

if(varD != null)
   [[self varD] release];

Fourth, do I need to take care of varA after assigning the new value in method1 if I did it well in the initClass and dealloc methods? In other words, will this generate memory leaks?

No memory leaks from NSString. This method returns an autoreleased object. When you assign a new value to [self varA], it will release the old object, and retain the new object.

Fifth, if I declare with autorelease this class like an instance variable in a ViewController (MyClass *c; ... c = [[[MyClass alloc] initClass:@"description"] autorelease];) and I set the @property, do I have to do a release if I use it with c=... instead of self.c=...? As far as I know the behavior is the same than in my example so I should use the setter/get method in the viewDidLoad or viewWillAppear and released it in the dealloc without self..

You don't need a release in either scenario. The alloc increases the release count by 1, the autorelease will decrease it to 0. If you did self.c, that would increase it to 2, and decrease to 0 (one decrease from autorelease, and one from the property) when your class is released. You do not need to do ANYTHING in dealloc.

Sixth and last one, for a instance variable is varA the same that self->varA?

Yes, they point to the same location in memory.

相关问答

更多
  • 在这一点上,我想到的是,带有@property的实例变量必须在类的init方法中没有自己的情况下使用,并在dealloc中释放它们 这与事实完全相反。 @property只是让变量在课堂外公开。 如果您有另一个类调用该对象,它将查找头文件(.h文件),如果它没有看到该名称的变量,它将在编译过程中发出警告,并在运行时发生错误。 当使用合成属性(顺便说一句,你的合成可以全部在一行上,但是并不重要,例如:@synthesize varA,varB,varC;),使用self会自动保留并保留一个保留计数。 - (i ...
  • 原因很简单:在事件处理程序被订阅时,事件的发布 者通过事件处理程序委托(假定委托是一个实例方法)持有对订户的引用。 如果发布者的寿命比订户的时间长,那么即使没有其他的用户参考,它也会保留用户。 如果您使用相同的处理程序取消订阅事件,那么是的,这将删除处理程序和可能的泄漏。 然而,根据我的经验,这很少是一个问题,因为通常我发现出版商和订阅者的寿命大致相同。 这是一个可能的原因...但在我的经验中,这是相当夸张的。 你的里程可能有所不同,当然你只需要小心。 The cause is simple to expl ...
  • 这里发生的事情是, NewView对象参与引用循环,并且该循环中的对象不会自动收集为CPython基于主引用计数的对象释放机制的一部分。 但是,它们最终应该作为CPython的循环垃圾回收器的一部分收集起来,或者您可以通过执行gc.collect()来强制执行该集合,因此在这里不应该存在实际的长期内存泄漏。 具有讽刺意味的是,试图通过向NewView添加NewView方法来检测最终集合NewView阻碍该进程,因为它会呈现NewView对象不可收集:至少在Python 2中,Python不会尝试收集包含具有 ...
  • 我假设你正在使用ARC。 如果你是我认为你的问题是你的CFArrayRef没有转让所有权。 我发现这篇文章所以我不需要复制我的意思。 I assume you are using ARC. And if you are I think your problem is your CFArrayRef not transferring ownership. I found this post so I don't need to duplicate what I mean.
  • 我仍然不明白一件事:如果Drawable未被声明为静态,为什么它不会在activity的onDestroy()方法中被销毁? Drawable被破坏,TextView被破坏,Activity被销毁 - 没有引用也没有内存泄漏。 不是它应该如何工作? 是的,这是它应该如何工作但它们可能不会立即在onDestroy()销毁。 垃圾收集器运行的确切时间无法预测。 有许多事情会引发这种情况。 例如,如果您的应用程序在允许的堆内存上运行不足,或者某些其他应用程序试图分配更多内存... 如果您希望立即销毁您的位图,您应 ...
  • 你的问题措辞有点奇怪。 但据我了解,您的Lua脚本引用了在外部代码中分配的对象。 只要Lua有这些引用,外部代码就不会释放这些资源。 而且你相信应该释放这些资源。 您应该检查的第一件事是您的Lua接口代码使用元方法来正确清理引用。 也就是说,当Lua完成对象引用时,会附加一个元方法( __gc ),它将通知外部代码Lua已完成该对象。 对于本文的其余部分,我将假设此代码存在且功能正常。 你应该自己验证一下。 鉴于这种假设,您所看到的内容有两个原因: 您的Lua代码已完成使用其所有引用,但尚未清除它们。 通过 ...
  • 这里的问题是静态数组PHPExcel_Calculation::$_workbookSets获取对每个工作簿的PHPExcel_Calculation对象的引用。 每次do_it()运行时都会增长。 因为对象因此永远不会超出范围,所以无法回收它们的内存和它们的属性等。 替换你的未unset(...); with PHPExcel_Calculation::unsetInstance($phpexcel); 并且内存泄漏消失了,因为这会从该数组中删除关联的对象(并且仅执行该操作)。 对于一般问题:循环引用不是 ...
  • 假设您将ClientviewController的modelA属性声明为@property @property(retain) , @property(copy) property @property(copy)或@property(mutableCopy) ,则保留该属性的值,因此必须将其释放。 编辑自2013年:假设您没有使用ARC。 ARC将为您做到这一点,因此通常不需要在ARC下实现dealloc 。 不使用ARC时,您需要释放您拥有的所有内容。 Assuming that you declared ...
  • 找到我想要的东西。 在项目属性对话框中的链接器|下 输入 将DLL指定为延迟加载的DLL。 一旦我这样做,Visual Studio不再报告任何内存泄漏。 Found what I wanted. In the project property dialogs, under Linker | Input Specify the dll as a Delay Loaded DLL. Once I did this, Visual Studio no longer reported any memory lea ...
  • continue语句导致至少一次泄漏。 循环的开始分配一个新的Setting值并继续离开循环体而不释放内存。 您需要删除它以防止泄漏。 Setting* s = new Setting; getline(file, line); if(line.empty()) { delete s; continue; } 总的来说,虽然你在这里玩手动内存管理,但很容易出错。 我强烈建议您考虑使用类似shared_ptr的类型而不是原始Setting* 。 它将使您的代码更加健壮 The co ...

相关文章

更多

最新问答

更多
  • 您如何使用git diff文件,并将其应用于同一存储库的副本的本地分支?(How do you take a git diff file, and apply it to a local branch that is a copy of the same repository?)
  • 将长浮点值剪切为2个小数点并复制到字符数组(Cut Long Float Value to 2 decimal points and copy to Character Array)
  • OctoberCMS侧边栏不呈现(OctoberCMS Sidebar not rendering)
  • 页面加载后对象是否有资格进行垃圾回收?(Are objects eligible for garbage collection after the page loads?)
  • codeigniter中的语言不能按预期工作(language in codeigniter doesn' t work as expected)
  • 在计算机拍照在哪里进入
  • 使用cin.get()从c ++中的输入流中丢弃不需要的字符(Using cin.get() to discard unwanted characters from the input stream in c++)
  • No for循环将在for循环中运行。(No for loop will run inside for loop. Testing for primes)
  • 单页应用程序:页面重新加载(Single Page Application: page reload)
  • 在循环中选择具有相似模式的列名称(Selecting Column Name With Similar Pattern in a Loop)
  • System.StackOverflow错误(System.StackOverflow error)
  • KnockoutJS未在嵌套模板上应用beforeRemove和afterAdd(KnockoutJS not applying beforeRemove and afterAdd on nested templates)
  • 散列包括方法和/或嵌套属性(Hash include methods and/or nested attributes)
  • android - 如何避免使用Samsung RFS文件系统延迟/冻结?(android - how to avoid lag/freezes with Samsung RFS filesystem?)
  • TensorFlow:基于索引列表创建新张量(TensorFlow: Create a new tensor based on list of indices)
  • 企业安全培训的各项内容
  • 错误:RPC失败;(error: RPC failed; curl transfer closed with outstanding read data remaining)
  • C#类名中允许哪些字符?(What characters are allowed in C# class name?)
  • NumPy:将int64值存储在np.array中并使用dtype float64并将其转换回整数是否安全?(NumPy: Is it safe to store an int64 value in an np.array with dtype float64 and later convert it back to integer?)
  • 注销后如何隐藏导航portlet?(How to hide navigation portlet after logout?)
  • 将多个行和可变行移动到列(moving multiple and variable rows to columns)
  • 提交表单时忽略基础href,而不使用Javascript(ignore base href when submitting form, without using Javascript)
  • 对setOnInfoWindowClickListener的意图(Intent on setOnInfoWindowClickListener)
  • Angular $资源不会改变方法(Angular $resource doesn't change method)
  • 在Angular 5中不是一个函数(is not a function in Angular 5)
  • 如何配置Composite C1以将.m和桌面作为同一站点提供服务(How to configure Composite C1 to serve .m and desktop as the same site)
  • 不适用:悬停在悬停时:在元素之前[复制](Don't apply :hover when hovering on :before element [duplicate])
  • 常见的python rpc和cli接口(Common python rpc and cli interface)
  • Mysql DB单个字段匹配多个其他字段(Mysql DB single field matching to multiple other fields)
  • 产品页面上的Magento Up出售对齐问题(Magento Up sell alignment issue on the products page)