Хорошо, так что, надеюсь, это достаточно субъективный вопрос для программистов, но здесь идет. Я постоянно расширяю свои знания языков и практики разработки программного обеспечения ... и столкнулся с чем-то, что просто не имеет для меня никакого смысла.
В C ++ объявления классов включают private:
методы и параметры в заголовочный файл, что, теоретически, это то, что вы передаете пользователю, чтобы включить, если вы сделаете их библиотекой lib.
В Objective-C, в @interface
основном , делают то же самое, заставляя вас перечислять свои закрытые члены (по крайней мере, есть способ получить закрытые методы в файле реализации).
Из того, что я могу сказать, Java и C # позволяют вам предоставлять интерфейс / протокол, который может объявлять все общедоступные свойства / методы и дает кодировщику возможность скрывать все детали реализации в файле реализации.
Зачем? Инкапсуляция является одним из основных принципов ООП, почему C ++ и Obj-C не имеют этой базовой способности? Есть ли какой-нибудь лучший метод обхода Obj-C или C ++, который скрывает всю реализацию?
Благодаря,
источник
Ответы:
Вопрос в том, должен ли компилятор знать, насколько велик объект. Если это так, то компилятор должен знать о закрытых членах, чтобы подсчитать их.
В Java есть примитивные типы и объекты, и все объекты размещаются отдельно, а переменные, содержащие их, действительно являются указателями. Следовательно, поскольку указатель является объектом фиксированного размера, компилятор знает, насколько велика вещь, которую представляет переменная, не зная фактического размера указанного объекта. Конструктор обрабатывает все это.
В C ++ объекты могут быть представлены локально или в куче. Поэтому компилятору необходимо знать, насколько велик объект, чтобы он мог выделить локальную переменную или массив.
Иногда желательно разделить функциональность класса на общедоступный интерфейс и частное все остальное, и именно здесь появляется метод PIMPL (Pointer to IMPLementation). У класса будет указатель на частный класс реализации, и методы общедоступного класса могут вызывать это.
источник
Из-за дизайна C ++, чтобы создать объект в стеке, компилятор должен знать, насколько он велик. Для этого ему нужно, чтобы все поля присутствовали в заголовочном файле, так как это все, что может видеть компилятор при включении заголовка.
Например, если вы определяете класс
тогда
sizeof(Foo)
естьsizeof(a) + sizeof(b)
. Если существует какой-то механизм для разделения приватных полей, тогда заголовок может содержатьс
sizeof(Foo) = sizeof(a) + ???
.Если вы действительно хотите скрыть личные данные, попробуйте идиому pimpl
в заголовке и определение
FooImpl
только вFoo
российском файле реализации.источник
Все это сводится к выбору дизайна.
Если вы действительно хотите скрыть подробности частной реализации класса C ++ или Objective-C, то вы либо предоставляете один или несколько интерфейсов, которые класс поддерживает (чистый виртуальный класс C ++, Objective-C @protocol), и / или вы создаете класс возможность конструировать себя путем предоставления статического метода фабрики или объекта фабрики классов.
Причина, по которой закрытые переменные отображаются в заголовочном файле / объявлении класса / интерфейсе @, заключается в том, что потребителю вашего класса может потребоваться создать его новый экземпляр, а клиентскому коду
new MyClass()
или[[MyClass alloc]init]
в коде клиента необходим компилятор, чтобы понять, насколько велик MyClass Объект для того, чтобы сделать выделение.Java и C # также имеют свои частные переменные, подробно описанные в классе - они не являются исключением из этого, но IMO парадигма интерфейса гораздо чаще встречается в этих языках. У вас может не быть исходного кода в каждом случае, но в скомпилированном / байт-коде достаточно метаданных, чтобы получить эту информацию. Поскольку C ++ и Objective-C не имеют этих метаданных, единственная опция - это фактические детали интерфейса class / @. В мире C ++ COM вы не раскрываете закрытые переменные каких-либо классов, но можете предоставить файл заголовка - потому что класс является чисто виртуальным. Объект фабрики классов также зарегистрирован для создания реальных экземпляров, и есть несколько метаданных в различных формах.
В C ++ и Objective-C раздавать заголовочный файл меньше, чем писать и поддерживать дополнительный файл interface / @ protocol. Это одна из причин, по которой вы часто видите частную реализацию.
Другой причиной в C ++ являются шаблоны - компилятор должен знать детали этого класса, чтобы сгенерировать версию этого класса, специализированную для предоставленных параметров. Размер членов класса будет варьироваться в зависимости от параметризации, поэтому он должен иметь эту информацию.
источник