Scala隐式类参数

时间:2017-03-07 19:54:16

标签: java scala

我有一个隐式参数定义为:

的类
 class Test(implicit one: String)

我想像这样实例化那个对象:

val grr = new Test("aha")

我收到以下异常。

error: too many arguments for constructor Test: ()(implicit one: String)Test
       val grr = new Test("aha")

但如果我这样称呼它

val grr = new Test()("haha")
grr: Test = Test@3bd40a57

我得到一个Test对象。

为什么Scala实例化隐式方法要求您在此实例中使用空参数调用对象?为什么会为这样的对象实例提供隐式空白参数列表?

2 个答案:

答案 0 :(得分:5)

首先,Test 不是一个隐式类。有关隐式类的讨论,请参阅this

相反,Test是一个没有显式构造函数参数但只有一个implicit String参数的类。这意味着你可以实例化Test的唯一方法就是像你一样明确地提供隐式参数,这是尴尬和失败的目的,或者在{{1}中只提供一个String在实例化时的范围,并让编译器"拿起它。"

换句话说,如果你在范围内有类似的东西:

implicit

然后你需要做的就是实例化implicit val s: String = "haha"

Test

如果你没有范围,编译器会告诉你。这是一件好事。

主要的是要确保你区分隐式参数和隐式类。

答案 1 :(得分:0)

隐式空白参数列表仅适用于构造函数,而不适用于所有方法。我想这可能是因为解析器需要区分对Test类型(或伴随对象)的引用和对构造函数的引用。如果它允许没有参数的构造函数,那么Test本身就不明确了。

通常在scala中,当你引用“隐式类”时,你会这样做:

lock = threading.Lock()
total_mem= 1024 * 1024 * 500 #500MB spare memory
@contextlib.contextmanager
def ensure_memory(size):
    global total_mem
    while 1:
        with lock:
            if total_mem > size:
                total_mem-= size
                break
        time.sleep(1) #or something else...
    yield 
    with lock:
        total_mem += size

def _load_root(url):
    ...
    r = requests.get(url, timeout=(settings.ENGINE_SCRAPER_REQUEST_TIMEOUT + i, 10 + i), verify=False, stream=True) #add the stream=True to make request wait on on loading the entire request
    ...
    with ensure_memory(r.headers['content-length']):
        #now do stuff here :)
        html = r.content 
        ...
        return {'success': True, 'root': root}

然后你可以这样做:

object Container {
   implicit class Test(val one: string)
}

它将隐式地将字符串转换为Test对象。