使超类的初始化器返回特定的子类?

时间:2015-05-25 11:29:21

标签: swift subclass

我正在Swift中创建一个单元框架,它有不同单位的测量超类和子类,如Mass和Volume。一个功能是允许框架正确猜测它创建的单元并返回正确的类。示例代码:

class Measurement {
   var unitString : String
   init(unknownUnit: String) {
       // checks if the unit is either Volume or Mass, and returns an instance of that class
   }
}

class Volume : Measurement {
    init(unitString: String) {

    }
}

class Mass : Measurement {
    init(unitString: String) {

    }
}

let mass = Mass("kg")                   // class: Mass
let volume = Volume("ml")               // class: Volume
let shouldBeVolume = Measurement("ml")  // class: Volume
let shouldBeMass = Measurement("kg")    // class: Mass

初始化时,是否有可能让继承的类创建特定子类的对象?

库名为Indus Valley,GitHub上的开源

2 个答案:

答案 0 :(得分:1)

如果您在超类中创建子类对象,那么您的应用程序将崩溃,因为对init方法的调用将是递归的。要测试你可以创建一个类的层次结构,并尝试在超类中创建子类对象。

您可以使用面临的设计模式来解决此问题。只需要创建一个Interface类,它在内部使用所有其他类并创建对象并返回。

class UnitConverter {
    class func measurement(unknownUnit: String) -> Measurement {
        if unknownUnit == "kg" {
            return Mass(unknownUnit)
        } else if unknownUnit == "ml" {
            return Volume(unknownUnit)
        }

        return Measurement(unknownUnit)
    }
}

答案 1 :(得分:0)

它通过父类知道它的子类(非常差的反模式!)来继续快速和松散地继续播放,但这可行...

class Measurement {
    var unitString : String

    class func factory(unknownUnit: String) -> Measurement {
        if unknownUnit == "kg" {
            return Mass(myUnit: unknownUnit)
        } else { // Random default, or make func return Measurement? to trap
            return Volume(myUnit: unknownUnit)
        }
    }

    init(myUnit: String) {
        // checks if the unit is either Volume or Mass, and returns an instance of that class
        self.unitString = myUnit
    }
}

class Volume : Measurement {
}

class Mass : Measurement {
}

let mass = Mass(myUnit: "kg")                   // class: Mass
let volume = Volume(myUnit: "ml")               // class: Volume
let shouldntBeVolume = Measurement(myUnit: "ml")  // class: Measurement
let shouldntBeMass = Measurement(myUnit: "kg")    // class: Measurement
let isVolume = Measurement.factory("ml")  // class: Volume
let shouldBeMass = Measurement.factory("kg")    // class: Mass