将可变 java 类 转换为不可变 scala 类
Converting mutable java classes to immutable scala classes
我有一个 class 功能类似这样的
class OutputFile(name: String, index: Int = 0){
val localFile = File.createTempFile(name, ".gz")
localFile.deleteOnExit()
val localFileOut =new FileOutputStream(localFile)
private[this] var bytesWritted: Int = 0
def write(line: Bytes): OutputFile = {
if(bytesWritten > SOMESIZE) flush //this function uploads the file to a different location and closes the localfile and localFileOut
try{
writeLine(line) //this writes the line to the localfile
this
}catch{
//If the file had been closed by flush create a new object
case IOException =>
val outFile = new OutputFile(name, index+1)
outfile.write(line)
outfile
}
//Other functions like flush and writeLine
}
但是现在我不能将此对象与不可变对象一起使用。来自 java 背景的我很难将此 class 转换为不可变样式。在 java 代码中,我们可以只为输出流使用一个全局变量,并在需要时更改它。
是否有更好的方法来实现这种情况。
为了使 OutputFile
的工作流程不可变,每次调用都必须 return 一个新的不可变实例,而不仅仅是交换输出文件的调用:
object OutputFile {
def apply(name: String): OutputFile = {
new OutputFile(name, newStream(name), 0)
}
private def newStream(name: String): FileOutputStream = {
val localFile = File.createTempFile(name, ".gz")
localFile.deleteOnExit()
new FileOutputStream(localFile)
}
}
class OutputFile(name: String, stream: FileOutputStream, bytesWritten: Int) {
val THRESHOLD = 1000000
def write(line: Bytes): OutputFile = write(line, 1)
private def write(line: Bytes, attempt: Int): OutputFile = {
try {
val written = writeLine(line) //this writes the line to the localfile
if (written > THRESHOLD) {
flush
new OutputFile(name, OutputFile.newStream(name), 0)
} else new OutputFile(name, stream, written)
} catch {
case x: IOException =>
if (attempt > 3) throw x
else write(line, attempt + 1)
}
}
// returns bytesWritten + length of line
private def writeLine(line: Bytes): Int = ???
// uploads file, closes and deletes it
private def flush: Unit = ???
}
我添加了一个伴生对象 OutputFile
,这样实际的构造函数就是新的不可变实例的构造函数,并抽象出新流的打开。
每次写入调用都会创建一个新的 OutputFile
并跟踪已写入当前文件的字节数。达到 THRESHOLD
后,将刷新文件并 returned 具有新流的新实例。 IOException
不再负责触发新文件(当我们知道我们已经刷新时才完成),而是重试最多 3 次尝试。
最后一句警告:这个 class 本质上仍然是有状态的,因为它确实处理文件 I/O。虽然这试图假装没有状态,但它假设 write 永远不会 在单个实例上被调用两次。
我有一个 class 功能类似这样的
class OutputFile(name: String, index: Int = 0){
val localFile = File.createTempFile(name, ".gz")
localFile.deleteOnExit()
val localFileOut =new FileOutputStream(localFile)
private[this] var bytesWritted: Int = 0
def write(line: Bytes): OutputFile = {
if(bytesWritten > SOMESIZE) flush //this function uploads the file to a different location and closes the localfile and localFileOut
try{
writeLine(line) //this writes the line to the localfile
this
}catch{
//If the file had been closed by flush create a new object
case IOException =>
val outFile = new OutputFile(name, index+1)
outfile.write(line)
outfile
}
//Other functions like flush and writeLine
}
但是现在我不能将此对象与不可变对象一起使用。来自 java 背景的我很难将此 class 转换为不可变样式。在 java 代码中,我们可以只为输出流使用一个全局变量,并在需要时更改它。
是否有更好的方法来实现这种情况。
为了使 OutputFile
的工作流程不可变,每次调用都必须 return 一个新的不可变实例,而不仅仅是交换输出文件的调用:
object OutputFile {
def apply(name: String): OutputFile = {
new OutputFile(name, newStream(name), 0)
}
private def newStream(name: String): FileOutputStream = {
val localFile = File.createTempFile(name, ".gz")
localFile.deleteOnExit()
new FileOutputStream(localFile)
}
}
class OutputFile(name: String, stream: FileOutputStream, bytesWritten: Int) {
val THRESHOLD = 1000000
def write(line: Bytes): OutputFile = write(line, 1)
private def write(line: Bytes, attempt: Int): OutputFile = {
try {
val written = writeLine(line) //this writes the line to the localfile
if (written > THRESHOLD) {
flush
new OutputFile(name, OutputFile.newStream(name), 0)
} else new OutputFile(name, stream, written)
} catch {
case x: IOException =>
if (attempt > 3) throw x
else write(line, attempt + 1)
}
}
// returns bytesWritten + length of line
private def writeLine(line: Bytes): Int = ???
// uploads file, closes and deletes it
private def flush: Unit = ???
}
我添加了一个伴生对象 OutputFile
,这样实际的构造函数就是新的不可变实例的构造函数,并抽象出新流的打开。
每次写入调用都会创建一个新的 OutputFile
并跟踪已写入当前文件的字节数。达到 THRESHOLD
后,将刷新文件并 returned 具有新流的新实例。 IOException
不再负责触发新文件(当我们知道我们已经刷新时才完成),而是重试最多 3 次尝试。
最后一句警告:这个 class 本质上仍然是有状态的,因为它确实处理文件 I/O。虽然这试图假装没有状态,但它假设 write 永远不会 在单个实例上被调用两次。