Да, вы правы, что вам нужно иметь согласованные методы equals()
и hashcode()
для вашего объекта, чтобы иметь возможность использовать distinct()
, потому что под прикрытием оператор distinct
использует HashSet
.
Версия distinct
с Func1
позволяет вам преобразовать объект во что-то, что вы хотите отличить (но должны реализовать согласованные методы equals
и hashcode
).
Предположим, у меня есть Observable<Person>
, где Person
выглядит следующим образом:
class Person {
String firstName;
String lastName;
}
Затем, чтобы подсчитать количество различных имен, я могу сделать это:
persons.distinct(person -> person.firstName).count();
Вы правы насчет map = dictionary. Я добавлю:
Еще одно концептуальное отличие - это поведение при вызове методов (отправке сообщений) для нулевых объектов (до нуля).
Java
MyClass myObject = null;
myObject.doSomething(); <-- results in a NullPointerException
Obj-C
id myObject = nil;
[myObject doSomething]; <-- is valid
Здесь - очень хороший ТАК вопрос об этом поведении.
Интерфейс = Протокол
Поле = Переменная экземпляра ("ivar")
ArrayList = Массив
вызвать метод = отправить сообщение
Вы перечислили правильно.
Философский ответ по поводу 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 не является конструктором! ;)
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.)
Вместо использования итераторов для простого перечисления, которые вы обычно используете, для классов, реализующих протокол FastEnumeration (интерфейс в java), простой
for (элемент класса * в контейнере)
http://developer.apple.com/documentation/Cocoa/Conceptual/ObjectiveC/Articles/ocFastEnumeration.html
Вне моей головы:
foo
/ setFoo
, а не getFoo
/ setFoo
.) IBAction
, хотя способ разработки графических интерфейсов пользователя в Какао сильно отличается от Java. class
определения классов определяются с помощью @interface
(для переменных экземпляра и объявлений методов) и @implementation
(для фактического код метода) директива.