Recentemente, comprei um Mac e o uso principalmente para desenvolvimento em C # no VMWare Fusion. Com todos os aplicativos Mac legais ao redor, comecei a pensar no Xcode à espreita com apenas um clique de instalação e aprender Objective-C.
A sintaxe entre as duas linguagens parece muito diferente, provavelmente porque Objective-C tem suas origens em C e C # tem suas origens em Java / C ++. Mas diferentes sintaxes podem ser aprendidas, então deve estar tudo bem.
Minha principal preocupação é trabalhar com a linguagem e se ela ajudará a produzir um código bem estruturado, legível e elegante. Eu realmente gosto de recursos como LINQ e var em C # e me pergunto se há recursos equivalentes ou melhores / diferentes em Objective-C.
Quais recursos de linguagem vou sentir falta de desenvolver com Objective-C? Quais recursos irei ganhar?
Edit: As comparações de framework são úteis e interessantes, mas uma comparação de linguagem é o que esta pergunta realmente está perguntando (em parte, minha culpa por originalmente marcar com .net
). Presumivelmente, o Cocoa e o .NET são estruturas muito ricas por si só e ambos têm sua finalidade, um voltado para o Mac OS X e o outro para Windows.
Obrigado pelos pontos de vista bem pensados e razoavelmente equilibrados até agora!
fonte
Respostas:
Nenhuma linguagem é perfeita para todas as tarefas e Objective-C não é exceção, mas existem algumas sutilezas muito específicas. Como usar
LINQ
evar
(para o qual não estou ciente de uma substituição direta), alguns deles são estritamente relacionados à linguagem e outros são relacionados à estrutura.( NOTA: Assim como C # é fortemente acoplado com .NET, Objective-C é fortemente acoplado com Cocoa. Portanto, alguns dos meus pontos podem parecer não relacionados a Objective-C, mas Objective-C sem Cocoa é semelhante a C # sem .NET / WPF / LINQ, rodando em Mono, etc. Não é assim que as coisas são normalmente feitas.)
Não pretendo elaborar completamente as diferenças, prós e contras, mas aqui estão alguns que vêm à mente.
Uma das melhores partes do Objective-C é a natureza dinâmica - em vez de chamar métodos, você envia mensagens, que o tempo de execução roteia dinamicamente. Combinado (criteriosamente) com a tipagem dinâmica, isso pode tornar muitos padrões poderosos mais simples ou mesmo triviais de implementar.
Como um superconjunto estrito de C, Objective-C confia que você sabe o que está fazendo. Ao contrário da abordagem gerenciada e / ou segura de tipos de linguagens como C # e Java, Objective-C permite que você faça o que quiser e experimente as consequências. Obviamente, isso pode ser perigoso às vezes, mas o fato de que a linguagem não o impede ativamente de fazer a maioria das coisas é bastante poderoso. ( EDITAR: devo esclarecer que C # também tem recursos e funcionalidades "inseguros", mas seu comportamento padrão é código gerenciado, que você deve cancelar explicitamente. Em comparação, apenas Java permite código typesafe e nunca expõe ponteiros brutos em da maneira que C e outros fazem.)
Categorias (adicionar / modificar métodos em uma classe sem subclassificar ou ter acesso ao código-fonte) é uma faca de dois gumes incrível. Ele pode simplificar muito as hierarquias de herança e eliminar o código, mas se você fizer algo estranho, os resultados podem ser confusos.
O Cocoa torna a criação de aplicativos GUI muito mais simples de várias maneiras, mas você precisa entender o paradigma. O design MVC é difundido no Cocoa, e padrões como delegados, notificações e aplicativos GUI multi-threaded são adequados para Objective-C.
As vinculações Cocoa e a observação de valores-chave podem eliminar toneladas de código de cola, e as estruturas Cocoa aproveitam isso amplamente. O despacho dinâmico de Objective-C trabalha lado a lado com isso, então o tipo do objeto não importa, contanto que seja compatível com o valor-chave.
Você provavelmente sentirá falta de genéricos e namespaces, e eles têm seus benefícios, mas na mentalidade e paradigma do Objective-C, eles seriam sutilezas em vez de necessidades. (Genéricos têm tudo a ver com segurança de tipos e evitando a conversão, mas a tipagem dinâmica em Objective-C torna isso essencialmente um problema. Os namespaces seriam bons se bem feitos, mas são simples o suficiente para evitar conflitos de que o custo indiscutivelmente supera os benefícios, especialmente para código legado.)
Para simultaneidade, Blocks (um novo recurso de linguagem no Snow Leopard e implementado em dezenas de APIs Cocoa) são extremamente úteis. Algumas linhas (frequentemente associadas ao Grand Central Dispatch, que faz parte do libsystem em 10.6) podem eliminar clichês significantes de funções de retorno de chamada, contexto, etc. (Blocos também podem ser usados em C e C ++ e certamente podem ser adicionados a C #, o que seria incrível.) NSOperationQueue também é uma maneira muito conveniente de adicionar simultaneidade ao seu próprio código, despachando subclasses NSOperation personalizadas ou blocos anônimos que o GCD executa automaticamente em um ou mais threads diferentes para você.
fonte
alloca
,. Isso simplesmente não os torna tão acessíveis - você precisa ativá-los explicitamente.Tenho programado em C, C ++ e C # há mais de 20 anos, comecei em 1990. Acabo de decidir dar uma olhada no desenvolvimento do iPhone e no Xcode e Objective-C. Ai meu Deus ... retiro todas as reclamações sobre a Microsoft, agora percebo como o código está ruim. Objective-C é muito complexo em comparação com o que C # faz. Fiquei estragado com C # e agora agradeço todo o trabalho árduo que a Microsoft colocou. Apenas ler Objective-C com invocações de método é difícil de ler. C # é elegante nisso. Essa é apenas minha opinião, eu esperava que a linguagem de desenvolvimento da Apple fosse tão boa quanto os produtos da Apple, mas querida, eles têm muito a aprender com a Microsoft. Não há dúvida de que o aplicativo C # .NET posso colocar um aplicativo em funcionamento muitas vezes mais rápido do que o XCode Objective-C. A Apple certamente deveria dar uma olhada no livro da Microsoft aqui e então teríamos o ambiente perfeito. :-)
fonte
"Just reading Objective-C with method invokes is difficult to read"
- aqui está apenas um argumento muito subjetivo que é mencionado aqui como contras do Obj-C. Todos os outros são apenas retórica discutível.Nenhuma revisão técnica aqui, mas eu apenas acho Objective-C muito menos legível. Dado o exemplo que o Cinder6 deu a você:
C #
Objective-C
Parece horrível. Eu até tentei ler 2 livros sobre ele, eles me perderam no início, e normalmente eu não entendo isso com livros / linguagens de programação.
Estou feliz por termos o Mono para Mac OS, porque se eu tivesse que confiar na Apple para me dar um bom ambiente de desenvolvimento ...
fonte
[NSMutableArray array]
(ele está perdendo memória) e a 4ª linha deve começar comNSString* x
ouid x
(erro de compilação) ... Sim, Objective-C não tem genéricos (honestamente não sinto falta deles), você não Não indexe objetos com sintaxe de array e as APIs geralmente são mais detalhadas. To-may-to, to-mah-to. Na verdade, tudo se resume ao que você prefere ver. (Você poderia escrever o mesmo código em C ++ STL e eu acharia horrível.) Para mim, código legível geralmente significa que o texto do código informa o que está fazendo e, portanto, o código Objective-C é preferível.List<T>.Remove
leva uma string como um argumento e remove a primeira ocorrência dessa string. Para remover por índice, você precisaRemoveAt
.removeObjectAtIndex:
, embora mais detalhada, também não é ambígua quanto ao que faz.strings[0]
estrings.RemoveAt(0)
diminui a clareza, pelo menos para mim. (Além disso, sempre me incomoda quando os nomes dos métodos começam com uma letra maiúscula ... Eu sei que é uma pequena coisinha, mas é simplesmente estranho.)O gerenciamento manual de memória é algo com o qual iniciantes em Objective-C parecem ter mais problemas, principalmente porque pensam que é mais complexo do que é.
Objective-C e Cocoa, por extensão, dependem de convenções sobre a aplicação; conheça e siga um conjunto muito pequeno de regras e você receberá muito de graça pelo tempo de execução dinâmico em troca.
A regra não 100% verdadeira, mas boa o suficiente para o dia a dia, é:
alloc
deve corresponder a umrelease
no final do escopo atual.alloc
então, ele deve ser retornado por emreturn [value autorelease];
vez de ser correspondido por umrelease
.A explicação mais longa segue.
O gerenciamento de memória é baseado na propriedade; apenas o proprietário de uma instância de objeto deve liberar o objeto, todos os outros devem sempre não fazer nada. Isso significa que em 95% de todo o código, você trata Objective-C como se fosse uma coleta de lixo.
E quanto aos outros 5%? Você tem três métodos para procurar; qualquer instância de objeto recebida desses métodos é de propriedade do escopo do método atual :
alloc
new
ounewService
.copy
emutableCopy
.O método tem três opções possíveis do que fazer com as instâncias de objeto de sua propriedade antes de sair:
release
se não for mais necessário.autorelease
.Então, quando você deve tomar posse proativamente, ligando
retain
? Dois casos:fonte
Claro, se tudo o que você viu em sua vida é Objective C, então sua sintaxe parece a única possível. Poderíamos chamá-lo de "virgem de programação".
Mas como muitos códigos são escritos em C, C ++, Java, JavaScript, Pascal e outras linguagens, você verá que ObjectiveC é diferente de todos eles, mas não de um jeito bom. Eles tinham um motivo para isso? Vamos ver outras linguagens populares:
C ++ adicionou muitos extras ao C, mas mudou a sintaxe original apenas o necessário.
C # adicionou muitos extras em comparação com C ++, mas mudou apenas coisas que eram feias em C ++ (como remover o "::" da interface).
Java mudou muitas coisas, mas manteve a sintaxe familiar, exceto nas partes em que a mudança era necessária.
JavaScript é uma linguagem completamente dinâmica que pode fazer muitas coisas que ObjectiveC não pode. Ainda assim, seus criadores não inventaram uma nova maneira de chamar métodos e passar parâmetros apenas para ser diferente do resto do mundo.
Visual Basic pode passar parâmetros fora de ordem, assim como ObjectiveC. Você pode nomear os parâmetros, mas também pode passá-los da maneira normal. O que quer que você use, é a forma normal delimitada por vírgulas que todos entendem. A vírgula é o delimitador usual, não apenas em linguagens de programação, mas em livros, jornais e linguagem escrita em geral.
Object Pascal tem uma sintaxe diferente de C, mas sua sintaxe é realmente MAIS FÁCIL de ler para o programador (talvez não para o computador, mas quem se importa com o que o computador pensa). Então, talvez eles tenham divagado, mas pelo menos o resultado é melhor.
Python tem uma sintaxe diferente, que é ainda mais fácil de ler (para humanos) do que Pascal. Então, quando eles mudaram, tornando-o diferente, pelo menos eles o tornaram melhor para nós, programadores.
E então temos ObjectiveC. Adicionando algumas melhorias ao C, mas inventando sua própria sintaxe de interface, chamada de método, passagem de parâmetro e tudo o mais. Eu me pergunto por que eles não trocaram + e - de modo que mais subtraia dois números. Teria sido ainda mais legal.
Steve Jobs estragou tudo ao apoiar ObjectiveC. Claro que ele não suporta C #, o que é melhor, mas pertence ao seu pior concorrente. Portanto, esta é uma decisão política, não prática. A tecnologia sempre sofre quando as decisões de tecnologia são feitas por razões políticas. Ele deve liderar a empresa, o que ele faz bem, e deixar as questões de programação para especialistas reais.
Tenho certeza de que haveria ainda mais aplicativos para iPhone se ele decidisse escrever iOS e oferecer suporte a bibliotecas em qualquer outra linguagem que não ObjectiveC. Para todos, exceto para os fãs obstinados, programadores virgens e Steve Jobs, ObjectiveC parece ridículo, feio e repulsivo.
fonte
NSArray
e ela lida com a seleção do melhor algoritmo com base na máquina e na natureza dos dados.Uma coisa que adoro no objetivo-c é que o sistema de objetos é baseado em mensagens, ele permite que você faça coisas realmente legais que você não poderia fazer em C # (pelo menos não até que eles suportem a palavra-chave dinâmica!).
Outra coisa excelente sobre como escrever aplicativos de cacau é o Interface Builder, muito mais agradável do que o designer de formulários no Visual Studio.
As coisas sobre obj-c que me incomodam (como um desenvolvedor C #) são o fato de que você tem que gerenciar sua própria memória (há coleta de lixo, mas isso não funciona no iPhone) e que pode ser muito prolixo por causa de a sintaxe do seletor e todos os [].
fonte
dynamic
só levará você até a metade - implementar um verdadeiro objeto dinâmico, mesmo com coisas triviais como delegação de mensagens, é entediante mesmo em C # 4.0. Por outro lado, o preço da flexibilidade verdadeira mensagem dinâmica que passa a la ObjC é a segurança de tipo perdida.System.Reflection
combinado com extensões em C # 3.0, você pode chamar qualquer método que encontrar, mas não é a verdadeira passagem de mensagem, parecerá queobj.PassMessage("function_name", params object[] args);
para uma melhor passagem de mensagem integrada à linguagem, o método ausente que pode ser chamado no objeto normal seria necessário.Como um programador que está começando a usar Objective-C para iPhone, vindo do C # 4.0, estou perdendo as expressões lambda e, em particular, Linq-to-XML. As expressões lambda são específicas do C #, enquanto o Linq-to-XML é realmente mais um contraste .NET vs. Cocoa. Em um aplicativo de amostra que eu estava escrevendo, tinha algum XML em uma string. Eu queria analisar os elementos desse XML em uma coleção de objetos.
Para fazer isso em Objective-C / Cocoa, tive que usar a classe NSXmlParser . Esta classe depende de outro objeto que implementa o NSXMLParserDelegate protocolo com métodos que são chamados (ler: mensagens enviadas) quando uma tag de abertura de elemento é lida, quando alguns dados são lidos (geralmente dentro do elemento) e quando alguma tag de final de elemento é lida . Você deve acompanhar o status e o estado da análise. E, honestamente, não tenho ideia do que acontece se o XML for inválido. É ótimo para obter detalhes e otimizar o desempenho, mas, cara, isso é muito código.
Em contraste, aqui está o código em C #:
E é isso, você tem uma coleção de objetos personalizados extraídos de XML. Se você quiser filtrar esses elementos por valor, ou apenas aqueles que contêm um atributo específico, ou se você quiser apenas os 5 primeiros, ou pular o primeiro 1 e obter os próximos 3, ou apenas descobrir se algum elemento foi retornado ... BAM, tudo ali na mesma linha de código.
Existem muitas classes de software livre que tornam esse processamento muito mais fácil em Objective-C, então isso faz muito do trabalho pesado. Não é apenas isso embutido.
* NOTA: Na verdade, eu não compilei o código acima, ele serve apenas como um exemplo para ilustrar a relativa falta de detalhamento exigida pelo C #.
fonte
Provavelmente a diferença mais importante é o gerenciamento de memória. Com C # você obtém a coleta de lixo, em virtude de ser uma linguagem baseada em CLR. Com Objective-C, você precisa gerenciar a memória sozinho.
Se você está vindo de C # (ou qualquer linguagem moderna), mudar para uma linguagem sem gerenciamento automático de memória será realmente doloroso, pois você gastará muito do seu tempo de codificação gerenciando adequadamente a memória (e depurando como bem).
fonte
Aqui está um artigo muito bom comparando os dois idiomas: http://www.coderetard.com/2008/03/16/c-vs-objective-c/
fonte
Além da diferença de paradigma entre as 2 línguas, não há muita diferença. Por mais que eu odeie dizer isso, você pode fazer o mesmo tipo de coisas (provavelmente não tão facilmente) com .NET e C # como faria com Objective-C e Cocoa. A partir do Leopard, Objective-C 2.0 tem coleta de lixo, então você não precisa gerenciar a memória sozinho, a menos que queira (compatibilidade de código com Macs mais antigos e aplicativos do iPhone são 2 motivos para querer).
No que diz respeito ao código estruturado e legível, grande parte da carga recai sobre o programador, como acontece com qualquer outra linguagem. No entanto, acho que o paradigma de passagem de mensagem se presta bem a código legível, desde que você nomeie suas funções / métodos de forma adequada (novamente, como qualquer outra linguagem).
Serei o primeiro a admitir que não estou muito familiarizado com C # ou .NET. Mas as razões que Quinn listou acima são algumas razões pelas quais eu não me importo em me tornar assim.
fonte
As chamadas de método usadas em obj-c facilitam a leitura do código, na minha opinião muito mais elegante do que c # e obj-c é construído sobre c, portanto, todo código c deve funcionar bem em obj-c. O que mais me vende é que obj-c é um padrão aberto, então você pode encontrar compiladores para qualquer sistema.
fonte