2016-11-04 1 views
1

Пару раз сейчас я столкнулся с проблемой, которая, по моему мнению, должна быть разрешимой для зависимых от пути типов, но я не уверен, что мне удалось это сделать поэтому самым полным или правильным способом. В мире Java нередко есть перечисление (или чаще всего псевдо-перечисление в виде кучи статических значений), которые определяют замкнутый набор, который сопоставляется с родными типами. java.sql.Types является хорошим примером:Scala для переходов на собственные типы с зависимыми от пути типами

public class Types { 

    /** 
    * <P>The constant in the Java programming language, sometimes referred 
    * to as a type code, that identifies the generic SQL type 
    * <code>BIT</code>. 
    */ 
    public final static int BIT    = -7; 

    /** 
    * <P>The constant in the Java programming language, sometimes referred 
    * to as a type code, that identifies the generic SQL type 
    * <code>TINYINT</code>. 
    */ 
    public final static int TINYINT   = -6; 

    /** 
    * <P>The constant in the Java programming language, sometimes referred 
    * to as a type code, that identifies the generic SQL type 
    * <code>SMALLINT</code>. 
    */ 
    public final static int SMALLINT  = 5; 
    // ... 
} 

Я хотел бы, чтобы обеспечить некоторое отображение, что возьмет меня от этих перечислений до их собственных типов. До сих пор у меня есть что-то вроде этого:

import java.sql.{Types, ResultSet} 

trait SqlType { 
    def typeValue:Int 
    type Value 
    def getValue(rs:ResultSet, idx:Int):Value 
} 

object SqlType { 

    object SqlInt extends SqlType { 
    type Value = Int 
    def typeValue = Types.INTEGER 
    def getValue(rs:ResultSet, idx:Int) = rs.getInt(idx) 
    } 

    object SqlString extends SqlType { 
    type Value = String 
    def typeValue = Types.NVARCHAR 
    def getValue(rs:ResultSet, idx:Int) = rs.getString(idx) 
    } 


    def getSqlType(typeValue:Int):SqlType = typeValue match { 
    case Types.INTEGER => SqlInt 
    case Types.NVARCHAR => SqlString 
    } 

    implicit class ResultSetExtras(rs:ResultSet) { 
    def getCell(idx:Int, sqlType:SqlType):sqlType.Value = sqlType.getValue(rs, idx) 
    } 
} 

Это немного шаткий, однако, как мне нужно, чтобы получить конкретный SqlType экземпляр, прежде чем руки и передать его в качестве аргумента функции, чтобы получить правильный путь в зависимости от тип. Так что это не кажется, что я могу сделать что-то вроде этого, что то, что я действительно люблю:.

implicit class ResultSetExtras2(rs:ResultSet) { 
    def getCell2(idx:Int):SqlType#Value = getSqlType(rs.getMetaData.getColumnType(idx)).getValue(rs, idx) 
    } 

(обратите внимание на тип возвращаемого SqlType#Value, а не зависимые от пути sqlType.Value Есть ли (лучше), чтобы достичь этого в чистом scala? Я подозреваю, что что-то вроде бесформенных или макросов может помочь, но, если возможно, я хотел бы знать, возможно ли это с зависимыми от пути типами (или макросами действительно предпочтение бесформенному).

ответ

1

Проблема в том, что во время компиляции для rs.getCell(2) знать, какой будет конкретный конкретный тип значения. Здесь вам не помогут. Тип результата может быть известен только во время выполнения. Это не проблема, если вы выберите абстрактный тип SqlType как возвращаемое значение (как в случае с java). Вы просто не можете получить действительный тип представленный SqlType#Value.

Смежные вопросы