Что такое некоторые различные названия условий и понятий в Objective C по сравнению с Java?

Да, вы правы, что вам нужно иметь согласованные методы equals() и hashcode() для вашего объекта, чтобы иметь возможность использовать distinct(), потому что под прикрытием оператор distinct использует HashSet.

Версия distinct с Func1 позволяет вам преобразовать объект во что-то, что вы хотите отличить (но должны реализовать согласованные методы equals и hashcode).

Предположим, у меня есть Observable<Person>, где Person выглядит следующим образом:

class Person {
    String firstName;
    String lastName;
}

Затем, чтобы подсчитать количество различных имен, я могу сделать это:

persons.distinct(person -> person.firstName).count();
10
задан user149100 1 August 2009 в 22:14
поделиться

7 ответов

Вы правы насчет map = dictionary. Я добавлю:

  • @public, @private, @protected (по умолчанию) предназначены только для переменных экземпляра (не методов) и работают как модификаторы видимости C ++ (т.е. вы объявляете их как заголовки разделов, а не перед каждой переменной).
  • Методы класса подобны статическим методам в Java
  • Есть только две структуры данных: NSDictionary и NSArray (в неизменяемом и изменяемом вариантах). Они хорошо оптимизированы и подходят для большинства ситуаций. Для всего остального есть CHDataStructures
  • @interface не работает как интерфейсы Java - он определяет переменные экземпляра и методы одного класса.
  • Вам нужны файлы заголовков. В этом виноват C. Это в значительной степени отстой, поскольку поддерживать вещи - ненужная боль.
  • Нет понятия «пакет». Наиболее близким является фреймворк, но их не следует использовать в качестве пакетов Java (т.е. не создавать их только для организации ваших классов).
  • Вместо «new Class ()» скажите [[Class alloc] init] . Думайте о "alloc" как об операторе new и о init как о конструкторе.
  • id - это универсальные указатели на объекты, такие как ссылки типа Object в Java.
  • Базовым классом является NSObject. Наследование от NSObject не является автоматическим и должно быть явно указано.
12
ответ дан 3 December 2019 в 16:53
поделиться

Еще одно концептуальное отличие - это поведение при вызове методов (отправке сообщений) для нулевых объектов (до нуля).

Java

MyClass myObject = null;
myObject.doSomething(); <-- results in a NullPointerException

Obj-C

id myObject = nil;
[myObject doSomething]; <-- is valid

Здесь - очень хороший ТАК вопрос об этом поведении.

3
ответ дан 3 December 2019 в 16:53
поделиться

Интерфейс = Протокол

Поле = Переменная экземпляра ("ivar")

ArrayList = Массив

вызвать метод = отправить сообщение

Вы перечислили правильно.

2
ответ дан 3 December 2019 в 16:53
поделиться

Философский ответ по поводу alloc / init.

init не является конструктором. Концептуально «конструкция» не существует в Objective-C. В Java (и других языках с конструкторами) вызов конструктора вернет новый экземпляр объекта, готового к работе. В Objective-C нет точного эквивалента. (Можно утверждать, что методы удобных классов, такие как + array, + arrayWithObjects и т. Д., Технически являются конструкторами, поскольку они охватывают как выделение, так и инициализацию, но я бы сказал, что они все еще не конструкторы в том же смысле, что и конструкторы Java.)

Вместо этого у нас есть концепция выделения и инициализации, два отдельных шага, которые при совместном выполнении действуют так, как если бы они были «конструктором». Метод класса + alloc просто запрашивает у системы кусок памяти подходящего размера. IIRC, он использует для этого функцию calloc (). Не гарантируется, что во время выполнения функции выделения произойдет какое-либо обнуление. Это означает, что нам нужно выполнить инициализацию самостоятельно, что мы делаем, немедленно вызывая метод -init.

ОДНАКО, -init (и все производные) являются не чем иным, как обычными методами экземпляра. Вы можете отправлять им сообщения, когда захотите, чтобы «сбросить» экземпляр объекта в исходное инициализированное состояние (хотя есть некоторые разветвления при управлении памятью, которые необходимо учитывать). Это также означает, что вы можете сделать что-нибудь нелепое вроде этого:

NSUInteger count = [[[NSArray alloc] autorelease] count];

Я не могу придумать вескую причину, по которой вы захотите это сделать, но дело в том, что вы можете . Далее следует подчеркнуть, что init не является конструктором . В приведенном выше примере объект существует к моменту возврата метода + alloc. Однако он может быть неправильно инициализирован, что означает, что беззнаковое целое число «count» может отличаться от нуля. Может быть, но было бы неправильно полагаться на такое поведение (если, конечно, не задокументировано иное).

Одно из преимуществ разбиения конструкции на распределение и инициализацию состоит в том, что мы можем иметь большую степень контроля над тем, что именно получается. инициализирован. В Java, например, у вас может быть только один конструктор для каждой сигнатуры метода. Другими словами, если у вас есть конструктор, который принимает единственный аргумент «Object», то это единственный конструктор, который может. Вы не можете создать другой конструктор, который также принимает один аргумент Object.

В Objective-C типы параметров не являются частью сигнатуры метода (известной как «селектор»), поэтому я могу создать инициализатор следующим образом:

- (id) initWithAnObject:(id)anObject;

Однако я также могу создать другой инициализатор:

- (id) initWithADifferentObject:(id)anObject;

Я могу настроить их для выполнения совершенно разных инициализаций объекта, для которого они вызываются. Это невероятно полезно!

Еще один действительно полезный аспект разделения конструкции на выделение и инициализацию - это то, что вы можете связывать инициализаторы. AFAIK, вы не можете вызывать конструкторы из конструкторов на таких языках, как Java (ну, вы можете , но это не дает того же эффекта). Однако в Objective-C вы можете сделать что-то вроде этого:

- (id) initWithCapacity:(NSUInteger)initialCapacity {
  if (self = [super init]) {
    [self setInitialCapacity:initialCapacity];
  }
  return self;
}

- (id) init {
  return [self initWithCapacity:0];
}

Теперь, когда вы размещаете / инициализируете объект, настроенный таким образом, он будет "перенаправлять" и используйте инициализатор initWithCapacity, даже если вы вызвали init. (Так работает метод init NSArray) Это означает, что вы можете использовать условные инициализаторы. Например, ваш метод -init отправляется одному инициализатору при определенных условиях, но при других условиях используется другой.

Таким образом, модель Objective-C «выделить и инициализировать» намного мощнее, чем идея построения . Вы, как программист, имеете гораздо больший контроль над начальной фазой настройки вашего объекта. Это действительно освобождающий сдвиг.

ps - init не является конструктором! ;)

ваш метод -init отправляется одному инициализатору при определенных условиях, но при других условиях используется другой.

Таким образом, модель Objective-C «выделить и инициализировать» намного мощнее, чем идея построения. Вы, как программист, имеете гораздо больший контроль над начальной фазой настройки вашего объекта. Это действительно освобождающий сдвиг.

ps - init не является конструктором! ;)

ваш метод -init отправляется одному инициализатору при определенных условиях, но при других условиях используется другой.

Таким образом, модель Objective-C «выделить и инициализировать» намного мощнее, чем идея построения. Вы, как программист, имеете гораздо больший контроль над начальной фазой настройки вашего объекта. Это действительно освобождающий сдвиг.

ps - init не является конструктором! ;)

3
ответ дан 3 December 2019 в 16:53
поделиться

Previous answers cover most of the "phrasebook" differences, but there are a several key conceptual differences that bear mentioning... (Note that I only mention pure Objective-C issues, not Cocoa.)

  • There is a flat namespace for classes, and one for protocols. There is no such thing as packages or package hierarchies. All class names must be distinct (and all protocol names must be distinct) in an application. This is generally accomplished by using ~2-letter prefixes.
  • Exceptions are reserved for exceptional flow, almost always as the result of programmer error. The purposes for which 95%+ of Java exceptions are better served by returning an NSError if needed.
  • Consider using categories instead of one-off subclasses, but both should be done judiciously and cautiously. (Categories make the inheritance hierarchy less constrained, but affect all instances of a class. They're often a solid choice when you would normally subclass, such as for UI elements.) Frequently (in both Objective-C and Java) the best solution is to use composition instead.
  • You can use dynamic typing nearly everywhere as desired, just be aware that it is a double-edged sword. It gets rid of the need for a lot of casts, but errors that would be caught at compile time in Java are pushed to runtime in Objective-C. Static typing can be used anywhere as desired, and provides greater compile-time safety. (Java developers often view non-static typing as a language deficiency, but would do well to understand the flexibility it makes possible.)
  • You can mix C functionality and libraries freely without JNI wrappers. But you also get all the cruft and limitations of straight C. Yes, it would be wonderful if we could do away with the need for header files, but it's just not going to happen for C-based languages. Life isn't always fair. :-)
2
ответ дан 3 December 2019 в 16:53
поделиться

Вместо использования итераторов для простого перечисления, которые вы обычно используете, для классов, реализующих протокол FastEnumeration (интерфейс в java), простой

for (элемент класса * в контейнере)

http://developer.apple.com/documentation/Cocoa/Conceptual/ObjectiveC/Articles/ocFastEnumeration.html

0
ответ дан 3 December 2019 в 16:53
поделиться

Вне моей головы:

  • Сериализация = Архивирование
  • Переменные экземпляра обычно доступны через свойства, а не через явные методы доступа get / set. (Раньше мы тоже писали аксессоры, но даже тогда они обычно имели форму foo / setFoo , а не getFoo / setFoo .)
  • Действие / кнопка / мышь / прослушиватель событий примерно эквивалентны IBAction , хотя способ разработки графических интерфейсов пользователя в Какао сильно отличается от Java.
  • Вместо одного блока class определения классов определяются с помощью @interface (для переменных экземпляра и объявлений методов) и @implementation (для фактического код метода) директива.
2
ответ дан 3 December 2019 в 16:53
поделиться