Наследование класса похоже на специализацию.
Подумайте о классе Person.
человек знает, как дыхание, ходить, говорить, кормить себя и т.д. (Так скажем, у всех людей есть метод MakeMeASandwich
.)
Человек может иметь специализированную работу: плотник, повар, сантехник, IT человек, водитель грузовика и т.д.
Если у вас есть переменная
Person *aPerson;
это указатель на Person. Вы не знаете, какую профессию он делает, вы просто знаете, что это Человек. Вы можете назначить объект Plumber этой переменной или объект Carpenter или любое другое специализированное Лицо, потому что все эти типы также относятся к общему классу Person.
Когда вы обращаетесь к aPerson, компилятор понятия не имеет, с какими людьми он разговаривает.
Компилятор может знать, что он может сказать Человеку сделать бутерброд и предположить, что все люди знают, как это сделать. (Все специализированные классы Person, как Карпентер и Водопроводчик наследует метод makeMeASandwich от своего родительского класса Person.)
Если вы не скажете компилятор:
«Лицо является Carpenter», то компилятор будет жаловаться, если вы просите Личность построить вам колоду, потому что ваш средний Человек не имеет метода buildADeck. У этого метода есть только люди типа Carpenter.
Когда вы говорите
[(Carpenter *)aPerson buildADeck]
Вы рассказываете компилятор «Лицо является Карпентер. Поверьте мне. Я знаю. Попросите его/ее, чтобы построить палубу.» Компилятор предполагает, что вы знаете, о чем говорите, и что этот Человек действительно является Карпентером. Он попросит Человека построить колоду.
Если во время выполнения объект Person, на который указывает переменная aPerson, не относится к типу Carpenter, программа выйдет из строя, потому что, когда вы сообщите шеф-кондитеру, чтобы построить колоду, он/она будет очень смущен и не знаю, что делать. Он может даже рассердиться и уйти.
Если вы говорите:
Person *aPerson = [[Carpenter alloc] init];
Вы сообщаете компилятору создать Карпентера, и сохранить его в переменной общего назначения «Человек». Компилятор незамедлительно забывает, что созданный им человек был Карпентером. Он просто знает, что это Человек.
Таким образом, компилятор будет ли жаловаться, если вы пытаетесь сказать
[aPerson buildADeck];
Вы должны сказать
[(Carpenter *)aPerson buildADeck]
Но, поскольку все люди знают, как сделать бутерброд, вы можете сказать,
[aPerson makeMeASandwich]
и имейте это в виду. Даже если Человек является водопроводчиком, он/она будет знать, как сделать сэндвич, и, надеюсь, сделает вас одним. Вероятно, это будет лучший сэндвич, если Человек будет поваром, но, по крайней мере, вы получите бутерброд.
вы можете также сказать
сантехник * aPlumber = [[сантехник Alloc] инициализации]; [aPlumber makeMeASandwich];
потому что Сантехники тоже люди, и знаете, как сделать бутерброды. (IN OOP terms, Plumbers наследуют метод makeMeASandwich от их родительского класса Person.)
Красноречивый, как всегда. Для меня это денежная линия: «Вы говорите компилятору о создании Плотника и храните его в переменной« Человек »общего назначения. Компилятор незамедлительно забывает, что созданный им человек был Карпентером. Он просто знает, что это Человек. Кристально ясно - спасибо. Извините, но есть _but_. В предыдущем посте, в вашем альтернативном решении, была цель назначить объект _ (метка, например) _ переменной UIView _control_: 'control = aLabel;'? Разве это еще не нужно было бы отличать как ярлык, чтобы получить доступ к свойствам метки? – iSofia
У вас есть оператор switch, который возвращает различные типы объектов UIView. В некоторых случаях он возвращает метку, в других случаях - кнопку. Поскольку все объекты UIView, вы можете сохранить любой из них в переменной типа UIView. Это было мое понимание вашей цели ... решить, какой тип объекта создать. –
Хорошо; Я вижу сейчас. Большое спасибо Дункан; искренне ценим вашу помощь в этих двух длинных постов. – iSofia