class Foo {
let result: CGFloat
init() {
result = calculate()
}
private func calculate() -> CGFloat {
// do many complex calculation with many codes
return 0
}
}
毫无疑问,错误发生了。
'self' used in method call 'calculate' before all stored properties are initialized`
我知道有几种方法可以解决这个问题。
var 而不是 let。例如var 结果懒惰。例如惰性结果:CGFloat = { return 0 } calculate() 设为class/static 或全局函数。例如 static func calculate()。但我认为这不是我想要的。
让let 表示不可变。虽然 result 的计算可能很复杂,但它确实是不可变的。所以 var 不是最佳实践。
calculate()init() 中的代码太多,既不符合习惯又令人讨厌
class/static静态函数中不能使用其他实例属性。
class Foo {
let foo1: CGFloat = 1.0
let foo2: CGFloat = 2.0
let foo3: CGFloat
let result: CGFloat
init() {
foo3 = foo1 * foo2
result = calculate()
}
private func calculate() -> CGFloat {
// do some calculation
let constants: CGFloat = 100
// (10 lines...)
return foo3 + constants
}
}
为了更清楚,我添加了另一个片段。事实上result和foo3是一样的。那么为什么 foo3 = foo1 * foo2 而 result = calculate() 呢?
那是因为result的计算(大概10行代码)比foo3的计算(只有一行)稍微复杂一点。如果我把所有这些代码都放在 init() 中,它会很乱。
<强>1。 var 而不是 let
class Foo {
let foo1: CGFloat = 1.0
let foo2: CGFloat = 2.0
let foo3: CGFloat
var result: CGFloat
init() {
foo3 = foo1 * foo2
result = calculate()
}
private func calculate() -> CGFloat {
// do some calculation
let constants: CGFloat = 100
// (10 lines...)
return foo3 + constants
}
}
它有效,但 result 不是不可变的。
<强>2。 懒惰
class Foo {
let foo1: CGFloat = 1.0
let foo2: CGFloat = 2.0
let foo3: CGFloat
lazy var result: CGFloat = {
calculate()
}()
init() {
foo3 = foo1 * foo2
}
private func calculate() -> CGFloat {
// do some calculation
let constants: CGFloat = 100
// (10 lines...)
return foo3 + constants
}
}
它有效,但 result 也不是不可变的。
<强>3。静态函数
class Foo {
let foo1: CGFloat = 1.0
let foo2: CGFloat = 2.0
let foo3: CGFloat
let result: CGFloat
init() {
foo3 = foo1 * foo2
result = Foo.calculate()
}
static private func calculate() -> CGFloat {
// do some calculation
let constants: CGFloat = 100
// (10 lines...)
return foo3 + constants
}
}
构建失败,
Instance member 'foo3' cannot be used on type 'Foo'
<强>4。关闭
class Foo {
let foo1: CGFloat = 1.0
let foo2: CGFloat = 2.0
let foo3: CGFloat
let result: CGFloat
private let calculate = { () -> CGFloat in
// do some calculation
let constants: CGFloat = 100
// (10 lines...)
return foo3 + constants
}
init() {
foo3 = foo1 * foo2
result = calculate()
}
}
构建失败,
Instance member 'foo3' cannot be used on type 'Foo'
<强>5。计算属性
class Foo {
let foo1: CGFloat = 1.0
let foo2: CGFloat = 2.0
let foo3: CGFloat
var result: CGFloat {
// do some calculation
let constants: CGFloat = 100
// (10 lines...)
return foo3 + constants
}
init() {
foo3 = foo1 * foo2
}
}
它有效,但结果是“var”,并且将针对每次使用进行计算。
6.工具类
class Foo {
let foo1: CGFloat = 1.0
let foo2: CGFloat = 2.0
let foo3: CGFloat
let result: CGFloat
init() {
foo3 = foo1 * foo2
result = Tool.calculate(foo3: foo3)
}
}
class Tool {
static func calculate(foo3: CGFloat) -> CGFloat {
// do some calculation
let constants: CGFloat = 100
// (10 lines...)
return foo3 + constants
}
}
它可以工作,但我们引入了一个 Tool 类。
1、2、6比较合适。 6适合复杂的计算。
多次提到“隐式展开的可选值”。我很困惑为什么直到看到this answer .
强>强>强>强>强>最佳答案
您没有提到的其他两种方法是将 result 变成其中一种
第三种是,将计算移动到它自己的类型/自由函数中,并将其提供给这个类。这可能是正确的解决方案。
Swift 根本不允许你做你想做的事:规则是在你对新实例的其他属性做任何事情之前,必须设置所有存储的属性。它采取强硬的观点,即任何不能证明是正确的都必须被禁止。
例如,如果您将 calculate 更改为从 result 中读取会怎样?或者如果子类这样做了怎么办?您会遇到值不仅未定义而且无法定义的情况。
关于swift - 提取 Swift 类常量属性的初始化代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54777833/
如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby
在我的gem中,我需要yaml并且在我的本地计算机上运行良好。但是在将我的gem推送到rubygems.org之后,当我尝试使用我的gem时,我收到一条错误消息=>"uninitializedconstantPsych::Syck(NameError)"谁能帮我解决这个问题?附言RubyVersion=>ruby1.9.2,GemVersion=>1.6.2,Bundlerversion=>1.0.15 最佳答案 经过几个小时的研究,我发现=>“YAML使用未维护的Syck库,而Psych使用现代的LibYAML”因此,为了解决
在rails源中:https://github.com/rails/rails/blob/master/activesupport/lib/active_support/lazy_load_hooks.rb可以看到以下内容@load_hooks=Hash.new{|h,k|h[k]=[]}在IRB中,它只是初始化一个空哈希。和做有什么区别@load_hooks=Hash.new 最佳答案 查看rubydocumentationforHashnew→new_hashclicktotogglesourcenew(obj)→new_has
我希望我的UserPrice模型的属性在它们为空或不验证数值时默认为0。这些属性是tax_rate、shipping_cost和price。classCreateUserPrices8,:scale=>2t.decimal:tax_rate,:precision=>8,:scale=>2t.decimal:shipping_cost,:precision=>8,:scale=>2endendend起初,我将所有3列的:default=>0放在表格中,但我不想要这样,因为它已经填充了字段,我想使用占位符。这是我的UserPrice模型:classUserPrice回答before_val
我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah
我正在使用active_admin,我在Rails3应用程序的应用程序中有一个目录管理,其中包含模型和页面的声明。时不时地我也有一个类,当那个类有一个常量时,就像这样:classFooBAR="bar"end然后,我在每个必须在我的Rails应用程序中重新加载一些代码的请求中收到此警告:/Users/pupeno/helloworld/app/admin/billing.rb:12:warning:alreadyinitializedconstantBAR知道发生了什么以及如何避免这些警告吗? 最佳答案 在纯Ruby中:classA
我有一个具有一些属性的模型:attr1、attr2和attr3。我需要在不执行回调和验证的情况下更新此属性。我找到了update_column方法,但我想同时更新三个属性。我需要这样的东西:update_columns({attr1:val1,attr2:val2,attr3:val3})代替update_column(attr1,val1)update_column(attr2,val2)update_column(attr3,val3) 最佳答案 您可以使用update_columns(attr1:val1,attr2:val2
我在Rails工作并有以下类(class):classPlayer当我运行时bundleexecrailsconsole然后尝试:a=Player.new("me",5.0,"UCLA")我回来了:=>#我不知道为什么Player对象不会在这里初始化。关于可能导致此问题的操作/解释的任何建议?谢谢,马里奥格 最佳答案 havenoideawhythePlayerobjectwouldn'tbeinitializedhere它没有初始化很简单,因为你还没有初始化它!您已经覆盖了ActiveRecord::Base初始化方法,但您没有调
我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("
我有这个html标记:我想得到这个:我如何使用Nokogiri做到这一点? 最佳答案 require'nokogiri'doc=Nokogiri::HTML('')您可以通过xpath删除所有属性:doc.xpath('//@*').remove或者,如果您需要做一些更复杂的事情,有时使用以下方法遍历所有元素会更容易:doc.traversedo|node|node.keys.eachdo|attribute|node.deleteattributeendend 关于ruby-Nokog