Как проверка типов работает в Swift - PullRequest
0 голосов
/ 18 декабря 2018

Мне интересно, как проверка типов работает со Swift, я немного поиграл и создал класс Living и класс Animal, который наследуется от класса Living.Класс Cat наследуется от класса Animal, а класс Dog не имеет родительского класса.

Моя иерархия классов пока:

class Living {
  let heartRatePerMin: Int
  init(heartRatePerMin: Int) {
      self.heartRatePerMin = heartRatePerMin
  }
}

class Animal: Living {
  let name: String

  init(name: String, heartRatePerMin: Int) {
      self.name = name
      super.init(heartRatePerMin: heartRatePerMin)
  }
}

class Cat: Animal {
  let meowsPerHour: Int

  init(meowsPerHour: Int, name: String) {
      self.meowsPerHour = meowsPerHour
      super.init(name: name, heartRatePerMin: 60)
  }
}

class Dog {
  let runningSpeed: Int

  init(runningSpeed : Int) {
      self.runningSpeed = runningSpeed
  }
}

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

let animal = Animal(name: "Daisy", heartRatePerMin: 80)
let dog = Dog(runningSpeed: 2)
let cat = Cat(meowsPerHour: 10, name: "Smokey")

    if animal is Animal {
        //Warning: 'is' test always true
    }

    if dog is Animal {
        //Warning: Cast from 'Dog' to unrelated type 'Animal' always fails
    }

    if cat is Animal {
        //Warning: 'is' test always true
    }

    if cat is Living {
        //Warning: 'is' test always true
    }

До сих пор я считаю, что компилятор проверяет, имеет ли данный класс объектов наследование проверяемого типа, и может выдавать предупреждения.

Затем я создал пустой протокол Grumpy:

protocol Grumpy {

}

После этого я согласился на Grumpy из моего Cat класса, но я не соответствовал моему Dog классу.

Теперь, когда я проверяю, являются ли типы моих объектов (кошка и собака) сварливыми, как показано ниже, я получаю предупреждение для кошки, поскольку класс Cat соответствует протоколу сварливости, но я не получаюЛюбое предупреждение для собаки.Это ничего не говорит.Но когда я проверил собаку на наличие типа «Животное» выше, он предупреждал, что она всегда будет неудачной.Почему он не может предоставить ту же информацию для этого случая?

    if cat is Grumpy {
        //Warning: 'is' test is always true
    }

    if dog is Grumpy {
        //Nothing
    }

Затем, учитывая мое отсутствие знаний CS и Swift, я также попытался сделать что-то еще, чтобы посмотреть, как он будет себя вести, я создал массив Any как anyArray.Затем создал переменную unknown, приведенную к cat как Any, равную unknown.Затем добавляется unknown к anyArray.После этого я попытался проверить, является ли первый индекс anyArray типом Cat, но опять же без предупреждения:

    var anyArray = [Any]()
    let unknown = cat as Any
    anyArray.append(unknown)

    if anyArray[0] is Cat {
        //Nothing.
    }

Итак, учитывая все, что я пробовал, мне интересно, как типпроверка работает, как для времени компиляции, так и для времени выполнения?Я знаю, что это был довольно длинный вопрос, но любой ответ будет с благодарностью.

1 Ответ

0 голосов
/ 18 декабря 2018

Я предполагаю, что вы знаете, что следующее действительно и почему:

// although living is of type Living, it stores an instance of Cat at runtime
let living: Living =  Cat(meowsPerHour: 10, name: "Smokey")

Давайте сначала рассмотрим это:

if dog is Grumpy {
    //Nothing
}

dog имеет тип Dog, нокомпилятор не знает, если во время выполнения dog будет хранить подкласс Dog, который соответствует Grumpy.Оператор if будет выполняться, если dog назначен так:

class GrumpyDog : Dog, Grumpy {
    // ...
}

dog = GrumpyDog(...)

if anyArray[0] is Cat {
    //Nothing.
}

Это потому, что anyArray[0] имеет тип Any.Компилятор не достаточно умен, чтобы знать, что во время выполнения anyArray[0] хранит Cat.Следовательно, нельзя быть уверенным, что is будет иметь значение true."Что, если это на самом деле Dog?"можно сказать.

...