我有一种情况,我总是需要运行一些依赖于对象本身的代码
public abstract class A{
public A(X x){
//init A stuff
x.getAList("stuff").add(this);
x.getAList("otherstuff").add(this);
}
}
public class B extends A{
public B(X x){
super(x);
//init B stuff
}
}
public class C extends A{
public C(X x){
super(x);
//init C stuff
x.getAList("otherstuff").remove(this);
x.getAList("morestuff").add(this);
}
}
public class SomeClass{
private X someX;
public A somefunc(boolean b){
if(b){
return new B(someX);
}else{
return new C(someX);
}
}
}
问题如下。在此示例中,我在构造函数中使用了 this。如果另一个线程试图通过 someX.getAList 访问该对象,则可能导致该线程在构造函数结束之前访问该对象。
您可以通过 somefunc 将对象添加到 AList
public class SomeClass{
private X someX;
public A somefunc(boolean b){
A a;
if(b){
a = new B(someX);
someX.getAList("stuff").add(a);
someX.getAList("otherstuff").add(a);
}else{
a = new C(someX);
someX.getAList("stuff").add(a);
someX.getAList("morestuff").add(a);
}
return a;
}
}
问题是 B 和 C 也可以在别处实例化,并且每次创建 B 或 C 时都需要以指定的方式添加它们。我不想将对象添加到 AList 是用户的责任,而是类的责任。我也不希望用户必须调用为他们执行此操作的 init 函数。另一方面,我不希望出现任何并发问题。
有没有一种方法或模式可以实现这一点?
Golang 有类似 defer 的东西,可以让你在函数/方法/构造函数完成后运行一段代码。
最佳答案
改为为父类(super class)和子类创建一个工厂方法,并将构造函数设为私有(private),迫使每个想要实例的人都使用工厂方法。工厂方法是一种返回完全构造的实例的方法。一旦实例完全构建(在工厂方法中调用构造函数之后),将实例添加到列表中,这样就没有线程可以获取不完整/未完成的实例。
工厂方法的要点是将所有初始化代码与任何非初始化代码严格隔离,以避免访问和暴露未初始化的字段。它还可以作为用户的选择器,自动返回合适的(子)类型,无需指定。( Interesting design-patterns )
abstract class A{
protected A(){
//constructor code goes here
}
public void afterFinalisation(final X x) {
x.getAList("stuff").add(this);
x.getAList("otherstuff").add(this);
}
}
class B extends A{
protected B(){
super();
//constructor code goes here
}
public static B create(final X x) {
final B returnValue = new B();
returnValue.afterFinalisation(x);
return returnValue;
}
}
class C extends A{
protected C(){
super();
//constructor code goes here
}
@Override
public void afterFinalisation(final X x) {
super.afterFinalisation(x);
x.getAList("otherstuff").remove(this);
x.getAList("morestuff").add(this);
}
public static C create(final X x) {
final C returnValue = new C();
returnValue.afterFinalisation(x);
return returnValue;
}
}
class SomeClass{
private final X someX = new X();
public A somefunc(final boolean b){
if(b){
return B.create(this.someX);
}else{
return C.create(this.someX);
}
}
}
构造函数代码归功于 coolcats iteration of my answer ,我试图避免将代码放入 protected 构造函数中,而是使用 init() 方法,这需要对最终字段进行大量不优雅的解决方法。
关于java - 在 Java 中总是在构造函数之后执行方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37380704/
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
我正在尝试设置一个puppet节点,但rubygems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由rubygems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby
我在使用omniauth/openid时遇到了一些麻烦。在尝试进行身份验证时,我在日志中发现了这一点:OpenID::FetchingError:Errorfetchinghttps://www.google.com/accounts/o8/.well-known/host-meta?hd=profiles.google.com%2Fmy_username:undefinedmethod`io'fornil:NilClass重要的是undefinedmethodio'fornil:NilClass来自openid/fetchers.rb,在下面的代码片段中:moduleNetclass
我想了解Ruby方法methods()是如何工作的。我尝试使用“ruby方法”在Google上搜索,但这不是我需要的。我也看过ruby-doc.org,但我没有找到这种方法。你能详细解释一下它是如何工作的或者给我一个链接吗?更新我用methods()方法做了实验,得到了这样的结果:'labrat'代码classFirstdeffirst_instance_mymethodenddefself.first_class_mymethodendendclassSecond使用类#returnsavailablemethodslistforclassandancestorsputsSeco
我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer
设置:狂欢ruby1.9.2高线(1.6.13)描述:我已经相当习惯在其他一些项目中使用highline,但已经有几个月没有使用它了。现在,在Ruby1.9.2上全新安装时,它似乎不允许在同一行回答提示。所以以前我会看到类似的东西:require"highline/import"ask"Whatisyourfavoritecolor?"并得到:Whatisyourfavoritecolor?|现在我看到类似的东西:Whatisyourfavoritecolor?|竖线(|)符号是我的终端光标。知道为什么会发生这种变化吗? 最佳答案
我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby1.9+ 关于ruby-主要:Objectwhenrun
我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re