Pull to refresh
1
0
Send message

Никто не говорит о том, что я не делаю подобное через интерфейс.
Но объясните, пожалуйста, зачем мне декораторы, если я могу заимплементить протокол (интерфейс в терминах obj-c) уже существующему библиотечному классу? И в этой имплементации пользовать базовый функционал класса.


Так что, о вкусах не спорят. =)

Допустим, есть какая-то сторонняя библиотека, которую уж очень нравится и хочется использовать. И во всем нашем коде используется типовой код использующий класс из библиотеки, значит выносим в отдельный метод. В той же Java этот метод будет жить в классе-хелпере (не бейте ногами с жавой не сильно знаком). А в обжективе можно расширить класс нужной нам типовой (для нас) функциональностью.

Абсолютно правильно, как пример:


@interface Counter
-(NSInteger) increment;
@end
// Добавляем новый функционал через категорию -
// элемент языка, который служит для расширения
// функциональности класса.
@interface Counter (CountByTen)
-(NSInteger) incrementByTen;
@end

// И где то в коде.
Counter *counter = [[Counter alloc] init];
[counter incrementByTen];

Если вас сильно заинтересовал язык, посмотрите доку Яббл о нем.

Кроме позднего связывания хотел бы добавить о возможности расширения классов «снаружи», в пользовательском коде, без наследования, чтобы обраватывать новые, ранее неизвестные сообщения.
Насколько мне известно, в Objective-C можно отправить любое сообщение любому объекту, даже то, на которое он не знает как отвечать, в C++ — можно вызвать только те методы, которые публичные.
Вставлю свои 5 копеек: в целом ваша реализация наиболее правильна, но если уж очень хочется без дочерних списков, то можно оставить текущую структуру данных и делать выборку по робительскому id.
Скоро людей, которые пишут на C++/C#/Java, вообще не останется. Так ли это? Не думаю

Я не говорю, что так делать нужно. Скорее это была просто деманстрация. И я согласен с вами, что это выглядит уж очень громоздко.
Как альтернативное решение могу предложить, с помощью пространств имён сделать состояние иммутабельным снаружи, а внутри неймспейса состояния и команд оставить возможность изменения объектов.

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


class State {
    public ImmutableArray<Ship> Ships { get; }
    public State (ImmutableArray<Ship> ships) {
        this.Ships = ships;
    }
}
class Ship {
    public ImmutableArray<Room> Rooms { get; }
    public Ship (ImmutableArray<Room> rooms) {
        this.Rooms = rooms;
    }
}
class Room {
    public int Level { get; }
    public Room(int level) {
        this.Level = level;
    }
}
// ...
Ship[] ships = state.Ships.ToArray();
Room[] rooms = ships[shipIndex].Rooms.ToArray();
rooms[roomIndex] = new Room(rooms[roomIndex].Level + 1);
ships[shipIndex] = new Ship(ImmutableArray.ToImmutableArray(rooms));
return new State(ImmutableArray.ToImmutableArray(ships));

Но как было сказано выше, тут многовато аллокаций.

Полагаю, если вы говорите о реактивном программировании, то стоит делать стейт иммутабельным, а метод Execute команды должен возвращать новый стейт с измененными параметрами. Но данный подход создает определенные проблемы с затратами ресурсов системы.

Information

Rating
Does not participate
Registered
Activity