我想用一个enum
参数调用一个类,并让Types
和collections<Type>
的类成员取决于此enum
参数。我愿意接受一个答案,那就是这正是抽象类和接口的目的,没有其他方法可以按照这些原则进行操作。我只是想确保我没有错过任何聪明的把戏。
例如,我想将电影帧的集合表示为字节数组或短裤数组,其中图像处理取决于颜色的通道深度和位深度。我相信标准做法是创建一个抽象类或接口,然后从每个enum
成员的类或接口继承。此标准解决方案需要多个文件,并将处理细节分成这些单独的文件。
以下类说明了没有接口或抽象类的尝试。问题在于,进入或退出此类的任何内容都具有类型Any
,并且必须显式进行强制转换。那是一个初学者。我对泛型还不太熟悉,是否可以提供解决方案。 JVM中有Type
个擦除操作,因此我认为这也是一个死胡同。我的示例是Kotlin,但我认为其他面向对象的语言也可以使用。
class MovieFrames(val nRow:Int,val nCol:Int, val type: ElementType) {
val list = mutableListOf<Any>()
val frameSize = nRow * nCol
fun nframe() = list.size
constructor(nRow: Int, nCol: Int, values: List<Any>, type: ElementType = ElementType.Gray8) :
this(nRow, nCol, type) {
when (type) {
ElementType.RGB8 -> values.forEach { list.add(it as ByteArray) }
ElementType.Gray8 -> values.forEach { list.add(it as ByteArray) }
ElementType.Gray16 -> values.forEach { list.add(it as ShortArray) }
}
}
fun saveToFile(filename: String) {
when (type) {
ElementType.RGB8 -> {/*put Red, Green, Blue bytes to disk*/ }
ElementType.Gray8 -> {/*put Bytes to disk*/ }
ElementType.Gray16 -> {/*put Bytes to disk with specific byte ordering*/ }
}
}
fun getFrame(f:Int) : Any {
return list[f]
}
}
enum class ElementType(bitDepth: Int, channels: Int) {
RGB8(8, 3),
Gray8(8, 1),
Gray16(16, 1);
}
答案 0 :(得分:0)
感谢您的建议和鼓励。从尤尼·吉布斯(Yoni Gibbs)的评论来看,“密封的类”是我寻求的“技巧”,即枚举和多态性的某种组合。关于泛型,花了两个Types
来封装基础存储对象以及如何表示像素。这是结合所有建议的结果。
//e.g. T=ByteArray, ShortArray
//e.g. E=Byte,Short
sealed class Frames<T,E>(val nrow:Int,val ncol:Int,val bitDepth:Int,val channelDepth:Int) {
val size=nrow*ncol //frame size
abstract val list:MutableList<T>
fun totalBytes() = list.size*size*bitDepth/8*channelDepth
abstract fun set(i:Int,data:E)
abstract fun get(i:Int): E
fun saveToDisk(filename:String)=saveByteArray(filename,toByteArray())
abstract fun toByteArray(isSmallEndian:Boolean=false):ByteArray
}
class Gray8Frame(nrow:Int,ncol:Int) :
Frames<ByteArray,Byte>(nrow,ncol,8,1) {
override val list= mutableListOf<ByteArray>()
override fun set(i: Int,data:Byte) {list[i/size][i%size]=data}
override fun get(i: Int)=list[i/size][i%size]
override fun toByteArray(isSmallEndian: Boolean)
= ByteArray(totalBytes()){get(it)}
}
class Gray16Frame(nrow:Int,ncol:Int) :
Frames<ShortArray,Short>(nrow,ncol,16,1) {
override val list= mutableListOf<ShortArray>()
override fun set(i: Int,data:Short) {list[i/size][i%size]=data}
override fun get(i: Int)=list[i/size][i%size]
override fun toByteArray(isSmallEndian: Boolean)
= list.flatMap { it.toByteList() }.toByteArray()
//implement short-->List<Byte>
}
class RGBFrame(nrow:Int,ncol:Int) :
Frames<ByteArray,List<Byte>>(nrow,ncol,8,3) {
override val list= mutableListOf<ByteArray>()
override fun set(i: Int,data:List<Byte>) {
list[i/size][3*i%size+0]=data[0]//Red
list[i/size][3*i%size+1]=data[1]//Green
list[i/size][3*i%size+2]=data[2]//Blue
}
override fun get(i: Int)=listOf(
list[i/size][3*i%size+0],//Red
list[i/size][3*i%size+1],//Green
list[i/size][3*i%size+2] //Blue
)
override fun toByteArray(isSmallEndian: Boolean)
= list.flatMap { it.asList() }.toByteArray()
}
fun saveByteArray(filename:String, byteArray: ByteArray) { } //save bytes here