Oop 用单个类和枚举参数(Kotlin)替换接口或抽象类
我想用Oop 用单个类和枚举参数(Kotlin)替换接口或抽象类,oop,generics,kotlin,Oop,Generics,Kotlin,我想用enum参数调用单个类,并让类成员的类型和集合取决于此enum参数。我愿意接受这样一个答案:这正是抽象类和接口的目的,没有其他方法可以沿着这条路线前进。我只是想确定我没有错过一个聪明的把戏 例如,我想将电影帧集合表示为字节数组或短片数组,其中图像处理取决于颜色的通道深度和位深度。我相信标准做法是创建一个抽象类或接口,然后为每个enum成员继承这些抽象类或接口。此标准解决方案需要多个文件,并将处理细节分离到这些单独的文件中 下面的类说明了不使用接口或抽象类的尝试。问题是,任何进入或退出此类的
enum
参数调用单个类,并让类成员的类型和集合取决于此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);
}
class电影框架(val nRow:Int,val nCol:Int,val type:ElementType){
val list=mutableListOf()
val frameSize=nRow*nCol
fun nframe()=list.size
构造函数(nRow:Int,nCol:Int,value:List,type:ElementType=ElementType.Gray8):
此(nRow、nCol、类型){
何时(输入){
ElementType.RGB8->values.forEach{list.add(它作为ByteArray)}
ElementType.Gray8->values.forEach{list.add(作为ByteArray添加)}
ElementType.Gray16->values.forEach{list.add(它作为ShortArray)}
}
}
趣味saveToFile(文件名:String){
何时(输入){
ElementType.RGB8->{/*将红色、绿色和蓝色字节放入磁盘*/}
ElementType.Gray8->{/*将字节放入磁盘*/}
ElementType.Gray16->{/*按特定字节顺序将字节放入磁盘*/}
}
}
fun-getFrame(f:Int):任何{
返回列表[f]
}
}
枚举类ElementType(位深度:Int,通道:Int){
RGB8(8,3),
格雷8(8,1),
灰色16(16,1);
}
感谢您的建议和鼓励。根据Yoni Gibbs的评论,密封类是我正在寻找的“技巧”,即枚举和多态性的某种组合。关于泛型,需要两种类型
来封装下划线存储对象以及像素的表示方式。下面是综合所有建议的结果
//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
//例如T=ByteArray,ShortArray
//e、 g.e=字节,短
密封类帧(val nrow:Int、val ncol:Int、val bitDepth:Int、val channelDepth:Int){
val size=nrow*ncol//帧大小
抽象值列表:可变列表
fun totalBytes()=列表。大小*大小*位深度/8*通道深度
抽象趣味集(i:Int,data:E)
抽象乐趣获取(i:Int):E
fun saveToDisk(文件名:String)=saveByteArray(文件名,toByteArray())
抽象数组(isSmallEndian:Boolean=false):ByteArray
}
类Gray8Frame(nrow:Int,ncol:Int):
帧(nrow,ncol,8,1){
override val list=mutableListOf()
覆盖乐趣集(i:Int,data:Byte){list[i/size][i%size]=data}
覆盖乐趣获取(i:Int)=列表[i/size][i%size]
重写数组(isSmallEndian:布尔值)
=字节数组(totalBytes()){get(it)}
}
类Gray16Frame(nrow:Int,ncol:Int):
帧(nrow,ncol,16,1){
override val list=mutableListOf()
覆盖乐趣集(i:Int,data:Short){list[i/size][i%size]=data}
覆盖乐趣获取(i:Int)=列表[i/size][i%size]
重写数组(isSmallEndian:布尔值)
=list.flatMap{it.toByteList()}.tobyterarray()
//实现短-->列表
}
类RGB帧(nrow:Int,ncol:Int):
帧(nrow,ncol,8,3){
override val list=mutableListOf()
覆盖乐趣集(i:Int,数据:List){
列表[i/size][3*i%size+0]=数据[0]//红色
列表[i/size][3*i%size+1]=数据[1]//绿色
列表[i/size][3*i%size+2]=数据[2]//蓝色
}
覆盖乐趣获取(i:Int)=列表(
列表[i/size][3*i%size+0],//红色
列表[i/size][3*i%size+1],//绿色
列表[i/size][3*i%size+2]//蓝色
)
重写数组(isSmallEndian:布尔值)
=list.flatMap{it.asList()}.toByteArray()
}
fun saveByteArray(文件名:String,byteArray:byteArray){}//在此处保存字节
枚举是对象。他们可以有行为。让枚举对象执行行为,而不是基于值(当
时)执行行为。例如,枚举可以定义create(…)
来处理构造逻辑values.forEach{list.add(它作为ByteArray)}
,以及用于保存逻辑的saveToFile(…)
。这种方法更面向对象,因为enum对象现在负责依赖于所述enum对象的行为。如果我误解了你的问题,请告诉我。这个问题不清楚,你使用的术语也不标准。要回答你的问题,需要重写你的代码,并教你相当多的知识。了解泛型、面向对象设计、应该对哪些操作负责,等等。否则,我们为你做的工作超出了问题的范围,基本上就是“重写这个,让它为我工作。”我认为文斯·埃米尔的解决方案也是我会做的。这是否为您提供了继续进行所需的足够信息?你可能需要考虑的其他东西,这是Kotlin所特有的,是使用的,这基本上是枚举的扩展。也许对于这种非特定的问题,也许是更好的视觉。JaysMnar在引用其他站点时,常常有助于指出这一点。