Örnek oluşturma neden olduğu gibi?


17

C # 'yı son altı ay boyunca öğrendim ve şimdi Java'ya giriyorum. Sorum, örnek oluşturma (gerçekten her iki dilde) hakkında ve daha da fazlası: Neden bu şekilde yaptıklarını merak ediyorum. Bu örneği ele alalım

Person Bob = new Person();

Nesnenin iki kez belirtilmesi için bir neden var mı? Hiç var something_else Bob = new Person()mı?

Sözleşmeden takip ediyor olsaydım daha fazla olurdu:

int XIsAnInt;
Person BobIsAPerson;

Ya da belki bunlardan biri:

Person() Bob;
new Person Bob;
new Person() Bob;
Bob = new Person();

Sanırım "bu şekilde yapılıyor" ifadesinden daha iyi bir cevap olup olmadığını merak ediyorum.


26
Kişi bir alt türü ise ne olur LivingThing? Yazabilirsiniz LivingThing lt = new Person(). Kalıtım ve arayüzleri arayın .
xlecoustillier

2
Person Bobçağrılan "reference to " türünde bir değişken bildirir . bir nesne oluşturur . Referanslar, değişkenler ve nesneler üç farklı şeydir! PersonBobnew Person()Person
user253751

5
Artıklıktan rahatsız mısınız? O zaman neden yazmıyorsunuz var bob = new Person();?
200_success

4
Person Bob();C ++ ile mümkündür ve neredeyse aynı anlama gelirPerson Bob = Person();
user60561

3
@ user60561 hayır, argüman almayan ve bir kişiyi döndüren bir işlevi bildirir.
Nikolai

Yanıtlar:


52

Bir şey var mı? Bob = new Person ()?

Evet, miras yüzünden. Eğer:

public class StackExchangeMember : Person {}

Sonra:

Person bob = new StackExchangeMember();
Person sam = new Person();

Bob da bir kişidir ve hüzünle, herkesten farklı muamele görmek istemez.

Ayrıca, Bob'u süper güçlerle donatabiliriz:

public interface IModerator { }
public class StackOverFlowModerator : StackExchangeMember, IModerator {}

IModerator bob = new StackOverFlowModerator();

Ve böylece, kaba bir şekilde, diğer herhangi bir moderatörden farklı muamele görmesi için ayakta durmayacak. Ve gizli moddayken herkesi aynı çizgide tutmak için forumun etrafında gizlice dolaşmayı sever:

StackExchangeMember bob = new StackOverFlowModerator();

Sonra kötü bir 1. poster bulduğunda görünmezlik pelerini fırlatır ve atlar.

((StackOverFlowModerator) bob).Smite(sam);

Ve sonra tüm masum ve şeyleri daha sonra hareket edebilir:

((Person) bob).ImNotMeanIWasJustInstantiatedThatWay();

20
Nesnelerinizin adlarını düşürdüyseniz, bu çok daha açık olur.
Monica ile Hafiflik Yarışları

38
Şartnameye iyi bir örnek; kötü kalıtım örneği. Bunu okuyan hiç kimseye lütfen kalıtım kullanarak kullanıcı rollerini çözmeye çalışmayın.
Aaronaught

8
@Aaronaught doğru. Farklı insanlar için ayrı sınıflar oluşturmayın. Bir bit alanı kullanın enum.
Cole Johnson

1
@Aaronaught Ne yapmamasını söylemek çok iyi, ama insanların yerine ne yapması gerektiğini söylemeden çok yararlı değil.
Pharap

5
@Pharap: Ben de tam olarak yapmış birçok diğer sorular . Basit yanıt, kullanıcıların (kimlik doğrulama / kimlik) ve güvenlik politikasının (yetkilendirme / izinler) ayrı endişeler olarak ele alınması ve güvenlik politikası için standart modellerin rol tabanlı veya talep tabanlı olmasıdır. Kalıtım, gerçekte kimlik doğrulaması yapan nesneyi tanımlamak için daha kullanışlıdır, örneğin bir LDAP uygulaması ve bir SQL uygulaması.
Aaronaught

34

İlk kod satırınızı alıp inceleyelim.

Person Bob = new Person();

Birincisi Personbir tür belirtimidir. C # 'da, bunu sadece

var Bob = new Person();

ve derleyici olacak sonucuna yapıcı çağrısından değişken Bob türünü Person().

Ama böyle bir şey yazmak isteyebilirsiniz:

IPerson Bob = new Person();

Kişinin tüm API sözleşmesini değil, yalnızca arayüz tarafından belirtilen sözleşmeyi yerine getirdiğiniz yerdir IPerson.


2
+1: IPersonBaşka bir IPersonuygulamaya kopyalanması / yapıştırılması gereken kod yazarken yanlışlıkla herhangi bir özel yöntem kullanmamamı sağlamak için kodumda örnek yapacağım .
Cort Ammon - Monica'yı

@CortAmmon Orada bir yazım hatası olduğunu düşünüyorum, açıkça bu kod üzerinde kopyalamak / yapıştırılabilir yerine "polimorfizm ile çalışmak" demek istedim: D
Benjamin Gruenbaum

@BenjaminGruenbaum, polimorfizmin bazı tanımları için ;-)
Cort Ammon - Reinstate Monica

@CortAmmon yanlışlıkla özel bir yöntemi nasıl çağırırsınız ? Elbette demek istediniz internal?
Cole Johnson

@ColeJohnson her iki şekilde. Karşılaştığım belirli bir vakayı düşünmenin privateanlamlı olduğu yazdım : somutlaştırılan sınıfın bir parçası olan fabrika yöntemleri. Benim durumumda, özel değerlere erişim norm değil istisna olmalıdır. Ben uzun ömürlü olacak kod üzerinde çalışıyorum. Bunu bu şekilde yaparsam, sadece herhangi bir özel yöntemi kendim kullanmam mümkün değil, aynı zamanda bir sonraki geliştirici bunu birkaç düzine yere kopyaladığında / yapıştırdığında ve geliştirici onları kopyaladıktan sonra, birisinin bir fırsat bulma şansını azaltır. özel yöntemleri "normal" davranış olarak kullanır.
Cort Ammon - Monica'yı

21
  1. Bu sözdizimi, C ++ 'dan bir miras, bu arada, her ikisine de sahip:

    Person Bob;

    ve

    Person *bob = new Bob();

    Geçerli kapsam içinde bir nesne yaratan ilki, ikincisi dinamik bir nesneye işaretçi yaratır.

  2. Kesinlikle sahip olabilirsiniz something_else Bob = new Person()

    IEnumerable<int> nums = new List<int>(){1,2,3,4}

    Burada, yerel değişkenin türünü belirten iki farklı şey yapıyorsunuz numsve 'List' türünde yeni bir nesne oluşturmak ve oraya koymak istediğinizi söylüyorsunuz.

  3. C # türü sizi kabul eder, çünkü çoğu zaman değişkenin türü, içine koyduğunuz şeyle aynıdır:

    var nums = new List<int>();
  4. Bazı dillerde, F # gibi değişken türlerini belirtmekten kaçınmak için elinizden geleni yaparsınız :

    let list123 = [ 1; 2; 3 ]

5
İkinci örneğinizin yeni bir Bob nesnesine bir işaretçi oluşturduğunu söylemek daha doğru olur. İşlerin depolanma şekli teknik olarak bir uygulama detayıdır.
Robert Harvey

4
"İlk olarak yığın üzerinde yerel nesne, ikincisi öbek üzerinde bir nesne oluşturur." Ah adamım, yine bu yanlış bilgilendirme değil.
Monica ile Hafiflik Yarışları

@LightnessRacesinOrbit daha iyi?
AK_

1
@AK_ "Dinamik" hemen hemen "yığın" anlamına gelir (yığın, platform tarafından kullanılan bellek modeli olduğunda), "otomatik", "yığın" dan çok farklıdır. Bunu yaparsanız new std::pair<int, char>(), üyelerin firstve secondçiftin otomatik depolama süresi vardır, ancak büyük olasılıkla öbek üzerinde ayrılırlar (dinamik depolama süresi pairnesnesinin üyeleri olarak ).
Angew artık SO '

1
@AK_: Evet, bu adlar tam olarak ne anlama geldiklerini gösterirken, bu "yığın" ve "yığın" saçmalıkları anlamına gelmez . Bütün mesele bu. Onları kafa karıştırıcı bulmanız, sadece onlara öğretme ihtiyacımızı güçlendirir, böylece tanıdık olduğu için yanlış / yanlış terminolojiye güvenmemeniz gerekir!
Monica ile Hafiflik Yarışları

3

int xVe arasında büyük bir fark vardır Person bob. An intbir ' intdir intve her zaman bir olmalı intve asla bir şeyden başka bir şey olamaz int. Başlatılmasanız bileintBildirdiğiniz zaman ( int x;) , yine intde varsayılan değere ayarlanmıştır.

Person bobBununla birlikte, beyan ettiğinizde, adın bobherhangi bir zamanda gerçekte ne anlama gelebileceği konusunda büyük bir esneklik vardır . A Personya da başka bir sınıfa, örneğin Programmer,Person ; nullhiç bir nesneye atıfta bulunmadan bile olabilir .

Örneğin:

  Person bob   = null;
  Person carol = new Person();
  Person ted   = new Programmer();
  Person alice = personFactory.functionThatReturnsSomeKindOfPersonOrNull();

Dil tasarımcıları kesinlikle daha Person carol = new Person()az sembolle aynı şeyi başaracak alternatif bir sözdizimi yapabilirlerdi , ancak yine de izin vermek zorunda kalacaklardı Person carol = new Person() (veya yukarıdaki dört örnekten birini yasadışı yapmak için garip bir kural koymak zorunda kalacaklardı ). Dili son derece özlü kod yazmaktan çok "basit" tutmakla daha fazla ilgileniyorlardı. Bu, daha kısa alternatif sözdizimi sağlama kararlarını etkilemiş olabilir, ancak her durumda, gerekli değildi ve vermediler.


1

İki bildirim farklı olabilir, ancak çoğu zaman aynıdır. Java'da yaygın olarak önerilen bir desen şöyle görünür:

List<String> list = new ArrayList<>();
Map<String, Integer> map = new HashMap<>();

Bu değişkenler listve maparayüzler kullanılarak bildirilir Listve Mapkod belirli uygulamaları başlatırken. Bu şekilde, kodun geri kalanı yalnızca arayüzlere bağlıdır ve kodun TreeMapgeri kalanı arayüzün HashMapdışındaki API'nin herhangi bir kısmına bağlı olamayacağı için , örnek oluşturmak için farklı bir uygulama sınıfı seçmek kolaydır Map.

İki türün farklı olduğu diğer bir örnek, örneklemek için belirli bir alt sınıfı seçen, daha sonra bunu taban türü olarak döndüren bir fabrika yönteminde yer alır;

Tür çıkarımı kaynak kodu yedekliliğini düzeltebilir. Örneğin Java ile

List<String> listOne = Collections.emptyList();

tür çıkarımı ve beyanı sayesinde doğru türde bir liste oluşturacak

static <T> List<T> emptyList(); 

Bazı dillerde, tür çıkarım daha da ileri gider, örneğin C ++

auto p = new Person();

BTW Java dili gibi, küçük harf tanımlayıcı adlarını kullanarak için güçlü kongre ayarlar bobdeğil Bob. Bu, örneğin package.Class ve Class.variable arasındaki belirsizliği önler.
Jerry101

... ve işte bu yüzden var clazz.
CVn

Hayır, clazzçünkü classbir anahtar kelime olduğundan tanımlayıcı olarak kullanılamaz.
Jerry101

... isimlendirme kuralları oldukları gibi olmasaydı sorun olmazdı. Classtamamen geçerli bir tanımlayıcıdır.
cHao

... olduğu gibi cLaSs,cLASS ve cLASs.
el.pescado

1

Layman'ın sözleriyle:

  • Bildirimi somutlaştırmadan ayırmak, nesneleri kullananların onları yaratanlardan ayrılmasına yardımcı olur
  • Bunu yaptığınızda, örneklenen tür bildirme türünün bir alt türü olduğu sürece, değişkeni kullanan tüm kodlar çalışacağı için polyporphism etkinleştirilir.
  • Güçlü yazılan dillerde, bir değişkeni türünü bildirmeniz gerekir, bunu yaparak var = new Process()ilk önce değişkeni bildirmezsiniz.

0

Aynı zamanda olanları kontrol etme seviyesiyle de ilgilidir. Bir nesnenin / değişkenin bildirimi otomatik olarak bir yapıcı çağırırsa, örneğin,

Person somePerson;

olduğu otomatik aynı

Person somePerson = new Person(blah, blah..);

varsayılan kurucular yerine nesneleri somutlaştırmak için (örneğin) statik fabrika yöntemlerini hiçbir zaman kullanamazsınız, yani yeni bir nesne örneği için bir kurucu çağırmak istemediğiniz zamanlar vardır.

Bu örnek açıklanmıştır Joshua Bloch 'ın Etkili Java (Madde ironik yeterli 1!)


Kitaplarla ilgili olarak, hem C # kitabım hem de Java kitabım Joyce Farrell'dan. Kursun belirttiği şey bu. Ayrıca C # ve Java çeşitli youtube videoları ile takviye oldum.
Jason Wohlgemuth

Eleştiri yapmıyordum, sadece bunun nereden geldiğine dair bir referans verdim :)
David Scholefield
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.