Eu aprendi C # nos últimos seis meses ou mais e agora estou investigando Java. Minha pergunta é sobre a criação de instâncias (em qualquer idioma, na verdade) e é mais sobre: Eu me pergunto por que eles fizeram dessa maneira. Veja este exemplo
Person Bob = new Person();
Existe um motivo para o objeto ser especificado duas vezes? Alguma vez haveria um something_else Bob = new Person()
?
Parece que se eu estivesse seguindo a convenção, seria mais como:
int XIsAnInt;
Person BobIsAPerson;
Ou talvez um destes:
Person() Bob;
new Person Bob;
new Person() Bob;
Bob = new Person();
Suponho que estou curioso para saber se há uma resposta melhor do que "é assim que se faz".
java
c#
object-oriented
Jason Wohlgemuth
fonte
fonte
LivingThing
? Você poderia escreverLivingThing lt = new Person()
. Procure por herança e interfaces.Person Bob
declara uma variável do tipo "referência aPerson
" chamadaBob
.new Person()
cria umPerson
objeto. Referências, variáveis e objetos são três coisas diferentes!var bob = new Person();
?Person Bob();
é possível em C ++ e significa quase a mesma coisa quePerson Bob = Person();
Respostas:
Sim, por causa da herança. E se:
Então:
Bob também é uma pessoa e, caramba, ele não quer ser tratado de maneira diferente de qualquer outra pessoa.
Além disso, poderíamos dotar Bob de super poderes:
E assim, por Deus, ele não aceitará ser tratado de maneira diferente de qualquer outro moderador. E ele gosta de esgueirar-se pelo fórum para manter todos na fila enquanto estão no modo anônimo:
Então, quando ele encontra um pobre primeiro pôster, ele joga sua capa de invisibilidade e ataca.
E então ele pode agir de forma inocente e outras coisas depois:
fonte
enum
.Vamos pegar sua primeira linha de código e examiná-la.
A primeira
Person
é uma especificação de tipo. Em C #, podemos dispensar isso simplesmente dizendoe o compilador inferirá o tipo da variável Bob da chamada do construtor
Person()
.Mas você pode escrever algo assim:
Onde você não está cumprindo todo o contrato da API da Pessoa, mas apenas o contrato especificado pela interface
IPerson
.fonte
IPerson
exemplo no meu código para garantir que não use acidentalmente nenhum método privado ao escrever um código que deve ser copiado / colável em outraIPerson
implementação.internal
?private
é significativo: métodos de fábrica que fazem parte da classe sendo instanciados. Na minha situação, o acesso a valores privados deve ser a exceção, não a norma. Eu trabalho no código que vai me sobreviver por muito tempo. Se eu fizer dessa maneira, não só não é provável que eu use métodos particulares, mas quando o próximo desenvolvedor copia / cola alguns locais e o desenvolvedor depois os copia, diminui as chances de alguém ver uma oportunidade de use métodos privados como comportamento "normal".Essa sintaxe é praticamente um legado do C ++, que, a propósito, possui os dois:
e
O primeiro a criar um objeto dentro do escopo atual, o segundo a criar um ponteiro para um objeto dinâmico.
Você definitivamente pode ter
something_else Bob = new Person()
Você está fazendo duas coisas diferentes aqui, declarando o tipo da variável local
nums
e diz que deseja criar um novo objeto do tipo 'Lista' e colocá-lo lá.O C # concorda com você, porque na maioria das vezes o tipo da variável é idêntico ao que você coloca nela:
Em alguns idiomas, você faz o possível para evitar especificar os tipos de variáveis como em F # :
fonte
new std::pair<int, char>()
, os membrosfirst
esecond
o par terão duração de armazenamento automático, mas provavelmente serão alocados no heap (como membros dopair
objeto dynamic-storage-duration ).Há uma enorme diferença entre
int x
ePerson bob
. Anint
é umint
é umint
e deve sempre ser umint
e nunca pode ser outra coisa senão umint
. Mesmo se você não inicializarint
quando o declarar (int x;
), ele ainda seráint
definido como o valor padrão.Quando você declara
Person bob
, no entanto, há uma grande flexibilidade quanto ao que o nomebob
pode realmente se referir a qualquer momento. Pode se referir a aPerson
, ou pode se referir a alguma outra classe, por exemploProgrammer
, derivada dePerson
; poderia até sernull
, referindo-se a nenhum objeto.Por exemplo:
Os designers de linguagem certamente poderiam ter feito uma sintaxe alternativa que teria conseguido a mesma coisa que
Person carol = new Person()
em menos símbolos, mas eles ainda teriam que permitirPerson carol = new Person()
(ou fazer alguma regra estranha que tornasse ilegal esse particular dos quatro exemplos acima). Eles estavam mais preocupados em manter a linguagem "simples" do que em escrever códigos extremamente concisos. Isso pode ter influenciado sua decisão de não fornecer a sintaxe alternativa mais curta, mas, em qualquer caso, não era necessário e eles não a forneceram.fonte
As duas declarações podem ser diferentes, mas geralmente são as mesmas. Um padrão comum recomendado em Java é semelhante a:
Estas variáveis
list
emap
são declaradas usando as interfacesList
eMap
enquanto o código instancia implementações específicas. Dessa forma, o restante do código depende apenas das interfaces e é fácil escolher diferentes classes de implementação para instanciar, comoTreeMap
, pois o restante do código não pode depender de nenhuma parte daHashMap
API que esteja fora daMap
interface.Outro exemplo em que os dois tipos diferem é em um método de fábrica que escolhe uma subclasse específica para instanciar e depois a retorna como o tipo base, para que o chamador não precise estar ciente dos detalhes da implementação, por exemplo, uma opção de "política".
A inferência de tipo pode corrigir a redundância do código-fonte. Por exemplo, em Java
construirá o tipo certo de lista graças à inferência de tipo e à declaração
Em algumas linguagens, a inferência de tipo vai além, por exemplo, em C ++
fonte
bob
, nãoBob
. Isso evita muita ambiguidade, por exemplo, package.Class vs. Class.variable.clazz
.clazz
é usado porqueclass
é uma palavra-chave, portanto não pode ser usado como um identificador.Class
é um identificador perfeitamente válido.cLaSs
,cLASS
ecLASs
.Nas palavras do leigo:
var = new Process()
não declarando a variável primeiro.fonte
É também sobre o nível de controle sobre o que está acontecendo. Se a declaração de um objeto / variável chamar automaticamente um construtor, por exemplo, se
era automaticamente o mesmo que
nunca seria possível usar (por exemplo) métodos estáticos de fábrica para instanciar objetos em vez de construtores padrão, ou seja, haverá momentos em que você não deseja chamar um construtor para uma nova instância de objeto.
Este exemplo é explicado em Joshua Bloch 's Effective Java (ponto 1 ironicamente!)
fonte