Bilgi bir sözleşmeden fazlasını mı saklıyor?


20

Java, C # ve güçlü bir şekilde yazılan, statik olarak kontrol edilen birçok dilde, aşağıdaki gibi kod yazmak için kullanılır:

public void m1() { ... }
protected void m2() { ... }
private void m2() { ... }
void m2() { ... }

Dinamik olarak kontrol edilen bazı diller, belirli bir sınıf üyesinin "özelliğinin" düzeyini ifade etmek için anahtar kelimeler sağlamaz ve bunun yerine kodlama kurallarına güvenir. Örneğin Python, alt üyeli özel üyelere ön ek uygular:

_m(self): pass

Bu tür anahtar kelimelerin dinamik olarak kontrol edilen dillerde sunulmasının, yalnızca çalışma zamanında kontrol edildiğinden çok az fayda sağlayacağı söylenebilir.

Ancak, bu anahtar kelimeleri statik olarak kontrol edilen dillerde sağlamak için iyi bir neden bulamıyorum. protectedHem can sıkıcı hem de dikkat dağıtıcı gibi oldukça ayrıntılı anahtar kelimelerle kodumu doldurma gereksinimi buluyorum . Şimdiye kadar, bu anahtar kelimelerin neden olduğu bir derleyici hatasının beni bir hatadan kurtaracağı bir durumda bulunmadım. Aksine, yanlışlıkla yerleştirilmiş protectedbir kütüphanenin kullanılmasını engellediğim durumlarda bulundum .

Bunu aklımda tutarak sorum şu:

Bilgi, bir sınıfın resmi arayüzünün bir parçasını tanımlamak için kullanılan programcılar arasındaki bir sözleşmeden daha fazlasını mı saklıyor?

Bir sınıfın gizli durumunun saldırıya uğramasını önlemek için kullanılabilir mi? Yansıma bu mekanizmayı geçersiz kılabilir mi? Derleyicinin bilgi gizlemesini zorunlu kılmasının önemi nedir?


10
Üzgünüz, Eric Lippert tatilde :)
Benjol

Sorunuzu anlamak biraz zor. Temelde birisinin özel bir üyeye dışarıdan erişip erişemeyeceğini mi soruyorsunuz?
Morgan Herlocker


@roncode: Bazı cevaplardan kendimi yeterince açık bir şekilde ifade etmediğimi söyleyebilirim. Özellikle anlamayı zorlaştıran şeyin ne olduğunu söyleyebilir misiniz? Açıklığa kavuşturmaya çalışacağım.
blubb

2
"Derleme zamanında bilgi sağlamak ve sonra sadece çalışma zamanında kontrol etmek saçmalıktır" - gerçekten? Microsoft'a daha iyi söyleyin, çünkü mevcut .NET çerçevesinin önemli bir kısmı buna dayanmaktadır: seçmeli olarak statik yazmayı seçme veya devre dışı bırakma. Bu gerçekten ne demek istediğini sanmıyorum; soru tekrar tekrar "statik" ve "dinamik" kontroller hakkında konuşur, ancak bunlar tip sisteminin karakteristikleridir; Burada gerçekten sorun olan şey derleme zamanı ve çalışma zamanı bağlamasıdır .
Aaronaught

Yanıtlar:


4

Java sertifikası için çalışıyorum ve bunun bir kısmı, erişim değiştiricileri nasıl yöneteceğiyle ilgili. Ve mantıklıdırlar ve düzgün kullanılmalıdırlar.

Python ile çalıştım ve öğrenme yolculuğum sırasında, python'da kongre olduğunu duydum çünkü onunla çalışan insanlar bunun ne anlama geldiğini ve nasıl uygulanacağını bilmeli. Bununla birlikte _m(self): pass, alt çizgide bu alanla uğraşmama konusunda beni uyaracaktır. Fakat herkes bu sözleşmeyi takip edecek mi? Javascript ile çalışıyorum ve söylemeliyim ki, yapmazlar . Bazen bir sorunu kontrol etmem gerekir ve bunun nedeni, kişinin yapmaması gereken bir şey yapmasıydı ...

Python lider alt çizgisi ile ilgili bu tartışmayı okuyun

Bilgi, bir sınıfın resmi arayüzünün bir parçasını tanımlamak için kullanılan programcılar arasındaki bir sözleşmeden daha fazlasını mı saklıyor?

Söylediklerimden, Evet.

Bir sınıfın gizli durumunun saldırıya uğramasını önlemek için kullanılabilir mi? Yansıma bu mekanizmayı geçersiz kılabilir mi? Derleyici tarafından uygulanan daha resmi bir mekanizmanın sağladığı başka avantajlar var mı?

Evet, bir sınıfın gizli durumunu güvence altına almak için kullanılabilir ve yalnızca bunun için değil, kullanıcıların davranışlarını nesnenin olması gerektiği gibi düşündükleri bir şeyle değiştirmek için nesnelerin durumu ile uğraşmasını önlemek için de kullanılabilir. çalışmakta. Bir geliştirici olarak, bunu planlamalı ve düşünmeli ve sınıfınızı mantıklı bir şekilde, davranışlarının kurcalanmayacağı bir şekilde tasarlamalısınız. Ve derleyici, iyi bir arkadaş olarak, erişim politikalarını uygulamak için kodu tasarladığınız şekilde tutmanıza yardımcı olacaktır.

DÜZENLENMİŞ Evet, yansıma olabilir, yorumları kontrol edin

Son soru ilginç bir soru ve bununla ilgili cevapları okumak istiyorum.


3
Yansıma genellikle erişim korumasını atlayabilir. Java ve C # için her ikisi de özel verilere erişebilir.
Mark H

Teşekkürler! Cevaplar burada: stackoverflow.com/questions/1565734/… açıklayın!
wleao

1
Javascript kültürü python kültüründen çok farklıdır. Python'un pep-08'i var ve neredeyse tüm python geliştiricileri bu sözleşmeleri takip ediyor. PEP-08 ihlalleri genellikle hata olarak kabul edilir. Bu yüzden javascript / php / perl / ruby ​​deneyiminin bu açıdan python deneyimine çok az şey çevirdiğini düşünüyorum: _private python'da çok iyi çalışıyor.
Mike Korobov

1
Bazı (ancak hepsi değil) programlama dillerinde, bilgi gizleme, düşman kodlarına karşı koruma sağlamak için kullanılabilir. Bilgi gizleme, düşman kullanıcılara karşı koruma sağlamak için kullanılamaz.
Brian

2
@PEP-08 ihlalleri sık sık "hata olarak kabul edilir" ve hiçbir Python geliştiricisi sözleşmeleri takip etmemeyi hayal etmezse, o zaman onları dil tarafından da uygulayabilirsiniz! Neden dil otomatik olarak yapabiliyorsa neden işe yaramaz?
Andres

27

"Özel" erişim belirteci, ilk gördüğünüzde oluşturduğu derleyici hatasıyla ilgili değildir. Gerçekte , özel üyeye sahip sınıfın uygulaması değiştiğinde, değişime tabi olan bir şeye erişmenizi engellemekle ilgilidir .

Başka bir deyişle, hala çalışırken kullanmaya izin vermemek, artık çalışmadığında yanlışlıkla kullanmaya devam etmenizi önler .

Delnan'ın önek kuralının altında belirttiği gibi, sözleşmeye uyulduğu ve doğru anlaşıldığı sürece değişime tabi olan üyelerin yanlışlıkla kullanılmasını önler. Kötü niyetli (veya cahil) bir kullanıcı için, o üyeye olası tüm sonuçlarla erişmelerini durdurmak için hiçbir şey yapmaz. Erişim belirteçleri için yerleşik desteğe sahip dillerde bu, cehalette (derleyici hatası) gerçekleşmez ve kötü amaçlı olduğunda (özel üyeye ulaşmak için garip yapılar) ağrılı bir başparmak gibi gözükür.

"Korumalı" erişim belirteci farklı bir hikaye - bunu sadece "oldukça halka açık değil" veya "çok özel gibi" olarak düşünmeyin. "Korumalı" , korumalı üyeyi içeren sınıftan türettiğinizde muhtemelen bu işlevi kullanmak isteyeceğiniz anlamına gelir . Korunan üyeler, varolan sınıfları değiştirmeden varolan sınıfların üstüne işlevsellik eklemek için kullanacağınız "uzantı arabiriminin" bir parçasıdır.

Yani, kısa özet:

  • public: Sınıfın örneklerinde güvenle kullanın, sınıfın amacı değişmez.
  • korumalı: Sınıfı genişletirken (sınıftan türetirken) kullanılacak - uygulamanın büyük ölçüde değişmesi gerekiyorsa değişebilir.
  • private: Dokunmayın! Beklenen arayüzlerin daha iyi uygulanmasını sağlamak için irade değişebilir.

3
Daha da önemlisi, "uygulama ayrıntısı, değişikliğe tabidir" konvansiyonunun uygulanmadığı herhangi bir (kolay anlaşılabilir, örneğin önde gelen alt çizgilerde olduğu gibi) , özel üyelerin kazara kullanılmasını da önler. Örneğin Python'da, aklı başında bir programcı dışarıdan özel bir üye kullanarak kod yazdığında (ve hatta kaşlarını çattı) neredeyse kaçınılmaz olduğunda, tam olarak ne yaptığını bilir ve gelecekteki sürümlerde potansiyel kırılmayı kabul eder. . Yani, Java programcılarının yansımayı kullanacağı bir durumdur.

3
@Simon Stelling - hayır, diyorum ki, özel bir şey yapan sınıfın orijinal uygulayıcısı size "bunu kullanma, burada herhangi bir davranış gelecekte değişebilir" diyor. Örneğin, bir sınıfın ilk önce iki nokta arasında bir mesafe içeren özel üye değişkeni, daha sonra performans nedeniyle iki nokta arasındaki mesafeyi içerebilir. Eski davranışa dayanan her şey sessizce kırılacaktı.
Joris Timmermans

1
@MadKeithV: Öyleyse, dil düzeyinde bir anahtar kelime "dokunma çünkü ..." diyen bir konvansiyondan aynı şey anlamına nasıl gelir? Sadece derleyici onu zorlar, ama sonra statik tartışmaya karşı dinamik tartışmaya geri döndük.

7
@Simon Stelling (ve Delnan) - bu bana "motor sınırlayıcısının hız sınırı işaretinden nasıl farklı olduğunu" sormak gibi bir şey.
Joris Timmermans

1
Aradaki farkın farkındayım ve orada olmadığını söylemedim. Yanıtınızın ve takip yorumlarınızın çoğunun yalnızca kurallara veya dil düzeyindeki anahtar kelimelerle yapılabilecek üyelere ve yöntemlere ilişkin ek açıklama türlerini açıkladığını ve gerçek farkı (dil düzeyinde uygulamanızın varlığı) okuyucu tarafından çıkartılabilir.

11

Başka biri tarafından tüketilecek bir kod yazıyorsanız, bilgi gizleme, arayüzü anlamak için çok daha kolay olabilir. "Başka biri", ekibinizdeki başka bir geliştirici, ticari olarak yazdığınız bir API'yi tüketen geliştiriciler veya "dang şeyin nasıl çalıştığını hatırlayamayan" gelecekteki benliğiniz olabilir. Sadece 4 yöntemi olan bir sınıfla çalışmak 40 olan bir sınıfla çalışmak çok daha kolaydır.


2
Tamamen katılıyorum, ama bu soruma cevap vermiyor. Diğer programcı onun yalnızca ön ekli üyelere bakması ya da ön ekli olmayan üyelere bakması gerektiğini anladığı sürece, benim sınıfımda mı _memberyoksa private membersınıfımda mı ihmal edilebilir public.
blubb

6
Evet, ancak dinamik bir dilde yazılmış bir sınıfın genel dokümantasyonu da bu 36 özel bölümü size atmaz (en azından varsayılan olarak değil).

3
@Simon Gerçek faydaları olduğu için, "sadece bir sözleşme" ifadesi yanıltıcıdır. "Sadece bir kongre" bir sonraki satırda kıvırcık parantez gibi bir şeydir. Faydaları olan bir sözleşme, anlamlı isimler kullanmak gibi bir şeydir, ki bu tamamen farklıdır. Özel bir şey ayarlamak birinin "gizli yöntemler" görmesini engelliyor mu? Hayır, belirlenirlerse değil.
Morgan Herlocker

1
@ Simon- ayrıca, yalnızca kullanımı güvenli olan yöntemlerin ortaya çıkarılması, kullanıcının sınıfı kullanmaya çalışırken bir şeyleri kırmaması olasılığını artırır. Binlerce kez çağrılırsa bir web sunucusunu çökertebilecek yöntemler kolayca olabilir. API kullanıcılarınızın bunu yapabilmesini istemezsiniz. Soyutlama sadece bir sözleşmeden daha fazlasıdır.
Morgan Herlocker

4

Ben arka plan için, sınıf değişmezleri hakkında okuyarak başlamak öneririz .

Bir değişmez, uzun bir hikayeyi kısaltmak için, bir sınıfın durumu boyunca, bir sınıfın ömrü boyunca doğru kalması beklenen bir varsayımdır .

Gerçekten basit bir C # örneği kullanalım:

public class EmailAlert
{
    private readonly List<string> addresses = new List<string>();

    public void AddRecipient(string address)
    {
        if (!string.IsNullOrEmpty(address))
            addresses.Add(address);
    }

    public void Send(string message)
    {
        foreach (string address in addresses)
            SendTo(address, message);
    }

    // Details of SendTo not shown
}

Burada neler oluyor?

  • Üye addressessınıf yapımında ilklendirilir.
  • Özeldir, bu yüzden dışarıdan hiçbir şey dokunamaz.
  • Bunu da yaptık readonly, böylece inşaattan sonra içeriden hiçbir şey ona dokunamaz (bu her zaman doğru / gerekli değildir, ancak burada yararlıdır).
  • Bu nedenle, Sendyöntem addressesasla olmayacak bir varsayım yapabilir null. Bu kontrolü yapmak zorunda değildir, çünkü değerin değiştirilebileceği bir yol yoktur .

Eğer başka sınıfların addressesalana yazmasına izin verilirse (yani öyleyse public), bu varsayım artık geçerli olmayacaktır. Sınıfta bu alana bağlı diğer her yöntemin açık null denetimleri yapmaya veya programı çökme riskine girmesi gerekir.

Yani evet, bir "konvansiyondan" çok daha fazlası; sınıf üyeleri üzerindeki tüm erişim değiştiricileri toplu olarak bu durumun ne zaman ve nasıl değiştirilebileceğine ilişkin bir dizi varsayım oluşturur. Bu varsayımlar daha sonra bağımlı ve birbirine bağımlı üyelere ve sınıflara dahil edilir, böylece programcılar programın tüm durumu hakkında aynı anda mantık yürütmek zorunda kalmazlar. Varsayımlar yapabilme yeteneği, yazılımdaki karmaşıklığı yönetmenin kritik bir unsurudur.

Bu diğer sorulara:

Bir sınıfın gizli durumunun saldırıya uğramasını önlemek için kullanılabilir mi?

Evet ve hayır. Güvenlik kodu, çoğu kod gibi, bazı değişmezlere güvenecektir. Erişim değiştiriciler, güvenilir arayanlara, onunla uğraşmamaları gereken işaretler olarak kesinlikle yararlıdır . Kötü amaçlı kodlar ilgilenmez, ancak kötü amaçlı kodların da derleyiciden geçmesi gerekmez.

Yansıma bu mekanizmayı geçersiz kılabilir mi?

Tabii ki yapabilir. Ancak yansıtma, arama kodunun bu ayrıcalık / güven düzeyine sahip olmasını gerektirir. Tam güven ve / veya yönetici ayrıcalıklarına sahip kötü amaçlı kod çalıştırıyorsanız, bu savaşı zaten kaybettiniz.

Derleyicinin bilgi gizlemesini zorunlu kılmasının önemi nedir?

Derleyici zaten yapar uygulanması. .NET, Java ve diğer benzeri ortamlarda çalışma zamanı da öyle - yöntem özelse yöntemi çağırmak için kullanılan opcode başarılı olmaz. Bu kısıtlamanın tek yolu güvenilir / yükseltilmiş kod gerektirir ve yükseltilmiş kod her zaman doğrudan programın belleğine yazılabilir. O gibi kadar zorlanan var olabilir , özel bir işletim sistemi gerektirmeden yürürlüğe.


1
@Simon: Burada "cehalet" i açıklığa kavuşturmamız gerekiyor. Bir yöntemin önekinin eklenmesi _sözleşmeyi belirtir, ancak zorunlu kılmaz. Bu , sözleşmeden habersiz olmayı zorlaştırabilir , ancak özellikle Yansıma gibi sıkıcı ve sık sık kısıtlayıcı yöntemlerle karşılaştırıldığında sözleşmeyi kırmayı zorlaştırmaz . Bir toplantıda "bunu kırmamalısın " der . Erişim değiştirici "sen diyor edemez bu kırmak". Ben am değil bir yaklaşım olduğunu söylemeye çalıştığı daha iyi onlar felsefesi bağlı ikisi de iyidir, ama onlar yine de çok farklı yaklaşımlardır - diğerinden daha.
Aaronaught

2
Bir benzetmeye ne dersiniz: A private/ protectedaccess değiştirici prezervatif gibidir. Birini kullanmak zorunda değilsiniz, ancak kullanmayacaksanız, zamanlamanızdan ve ortaklarınızdan emin olsanız iyi olur. Kötü niyetli bir eylemi engellemez ve her seferinde işe yaramayabilir, ancak kesinlikle dikkatsizlik risklerini azaltacaktır ve "lütfen dikkatli olun" demekten çok daha etkili bir şekilde gerçekleştirecektir. Oh, ve eğer bir tane varsa, ama kullanmayın, o zaman benden sempati beklemeyin.
Aaronaught

3

Bilgi gizleme bir sözleşmeden çok daha fazlasıdır; etrafta dolaşmaya çalışmak aslında birçok durumda sınıfın işlevselliğini bozabilir. Örneğin, bir privatedeğişkeni bir değişkende saklamak , aynı zamanda bir protectedveya publicözelliğini kullanarak göstermek ve alıcıda null olup olmadığını kontrol etmek ve gerekli olan başlatma işlemini yapmak (yani, tembel yükleme) oldukça yaygın bir uygulamadır . Ya da bir privatedeğişkeni bir şeyde saklayın , bir özelliği kullanarak ortaya çıkarın ve ayarlayıcıda değerin değişip değişmediğini ve ateş PropertyChanging/ PropertyChangedolayları kontrol edin . Ancak dahili uygulamayı görmeden, perde arkasında neler olduğunu asla bilemezsiniz.


3

Bilgi gizleme, yukarıdan aşağıya tasarım felsefesinden gelişti. Python'a aşağıdan yukarıya dil denir .

Bilgi gizleme, Java, C ++ ve C # 'da sınıf düzeyinde iyi bir şekilde uygulanmaktadır, bu yüzden bu düzeyde gerçekten bir kongre değildir. Genel arabirimler ve gizli (özel) ayrıntılarla bir sınıfı "kara kutu" haline getirmek çok kolaydır.

İşaret ettiğiniz gibi, Python'da her şey görünür olduğu için gizli olması amaçlananları kullanmama kuralını takip etmek programcılara kalmış.

Java, C ++ veya C # ile bile, bir noktada bilgi gizleme bir kural haline gelir . Daha karmaşık yazılım mimarilerindeki en yüksek soyutlama düzeylerinde erişim kontrolü yoktur. Örneğin, Java'da ".internal" kullanımını bulabilirsiniz . paket adları. Bu yalnızca bir adlandırma kuralıdır, çünkü bu tür bilgilerin gizlenmesinin yalnızca pakete erişilebilirlik yoluyla uygulanması kolay değildir.

Erişimi resmi olarak tanımlamaya çalışan bir dil Eyfel'dir. Bu makalede , Java gibi dillerin bilgi gizleme konusunda bazı diğer zayıf yönleri vurgulanmaktadır.

Tarihsel Bilgiler : Bilgi gizleme 1971 yılında David Parnas tarafından önerildi . Bu makalede, diğer modüller hakkında bilgi kullanımının "sistem yapısının bağlantısını feci şekilde artırabileceğini" belirtiyor. Bu fikre göre, bilgi gizleme eksikliği bakımı zor sıkıca bağlı sistemlere yol açabilir. Devam ediyor:

Sistem yapısının, programcı başlamadan önce, bir programcının bilgi kullanımından ziyade, tasarımcılar tarafından açıkça belirlenmesini istiyoruz.


1
+1 "programcı bilgileri kullanımı", bu tam olarak (sonunda ekstra bir virgül olmasına rağmen).
jmoreno

2

Ruby ve PHP bunu yapar ve çalışma zamanında uygular.

Bilgi gizleme noktası aslında bilgi göstermektir. İç detayları "gizleyerek" amaç dış bir perspektiften belirginleşir. Bunu kucaklayan diller var. Java'da erişim varsayılan olarak dahili pakete, korumalı haXe'ye. Açık bir şekilde ifşa etmeleri için herkese açık olarak beyan ediyorsunuz.

Bütün mesele, sadece son derece tutarlı bir arayüz ortaya koyarak sınıflarınızın kullanımını kolaylaştırmaktır. Gerisini korumak istersiniz, böylece zeki bir adam gelmez ve sınıfınızı istediği şeyi yapmak için kandırmak için içsel durumunuzu karıştırmaz.

Erişim değiştiricileri zamanında uygulanmasını, ayrıca, sen yapabilirsiniz güvenlik belirli bir düzeyde uygulamak için bunları kullanmak, ama bu özellikle iyi bir çözüm olduğunu düşünmüyorum.


1
Kütüphaneniz çalıştığınız aynı şirkette kullanılıyorsa, umursacaksınız ... Uygulamasını kilitlerse düzeltmekte zorlanacaksınız.
wleao

1
Neden takabileceğiniz bir emniyet kemeri takıyorsunuz? Ben soruyu başka bir şekilde ifade ve sorardım bir derleyici için herhangi bir neden yoktur değil tüm bilgilerin kendisine varsa, bunu uygulamak. Emniyet kemerinin takmaya değer olup olmadığını öğrenmek için bir kaza yapana kadar beklemek istemezsiniz.
Mark H

1
@Simon: neden insanların kullanmasını istemediğiniz şeylerle bir arayüz karıştırın. C ++ her üyenin bir başlık dosyasında sınıf tanımında mevcut olmasını gerektirir nefret ediyorum (nedenini anlıyorum). Arayüzler diğer insanlar içindir ve kullanamayacakları şeylerle dolup taşmamalıdır.
phkahler

1
@phkahler: arayüzden pydockaldırılır _prefixedMembers. Karmaşık arayüzlerin derleyici tarafından kontrol edilen bir anahtar kelime seçimi ile ilgisi yoktur.
blubb

2

Erişim değiştiriciler kesinlikle sözleşmenin yapamayacağı bir şey yapabilir.

Örneğin, yansıma kullanmadığınız sürece Java'da özel üyeye / alana erişemezsiniz.

Bu nedenle, bir eklenti için arabirim yazar ve özel alanları yansıma yoluyla değiştirme haklarını reddedersem (ve güvenlik yöneticisini ayarla) :), herkes tarafından uygulanan işlevlere bazı nesneler gönderebilir ve özel alanlarına erişemediğini bilirim.

Elbette, bunun üstesinden gelmesine izin verecek bazı güvenlik hataları olabilir, ancak bu felsefi olarak önemli değildir (ancak pratikte kesinlikle öyle).

Kullanıcı arayüzümü kendi ortamında çalıştırırsa, kontrolü vardır ve böylece erişim değiştiricilerini atlatabilir.


2

Bu anahtar kelimelerin neden olduğu bir derleyici hatasının beni bir hatadan kurtaracağı bir durumda bulunmadım.

Uygulama yazarlarını hatalardan kurtarmak, kütüphane yazarlarının uygulamalarının hangi bölümlerini sürdürmeye karar verdiklerine izin verecek kadar fazla değildir.

Kütüphanem varsa

class C {
  public void foo() { ... }

  private void fooHelper() { /* lots of complex code */ }
}

fooUygulamasının yerini alabilir ve muhtemelen fooHelperradikal yollarla değişebilirim . fooHelperBelgelerimdeki tüm uyarılara rağmen bir grup insan kullanmaya karar verdiyse bunu yapamayabilirim.

privateKütüphane yazarlarının privateyıllardır bu iç detayları korumaya zorlanacakları korkusu olmadan kütüphaneleri yönetilebilir büyüklükteki yöntemlere (ve yardımcı sınıflara) ayırmalarına izin verir .


Derleyicinin bilgi gizlemesini zorunlu kılmasının önemi nedir?

Yan notta, Java'da privatederleyici tarafından değil, Java bayt kodu doğrulayıcısı tarafından zorlanır .


Yansıma bu mekanizmayı geçersiz kılabilir mi? Derleyicinin bilgi gizlemesini zorunlu kılmasının önemi nedir?

Java'da sadece yansıma bu mekanizmayı geçersiz kılamaz. privateJava'da iki tür vardır . Bunun türü, privatebir dış sınıfın başka bir dış sınıfın privatebayt kodu doğrulayıcısı tarafından denetlenen üyelerine erişmesini engellemez , aynı zamanda privatebir iç sınıf tarafından paket özel sentetik erişimci yöntemi ile kullanılan s

 public class C {
   private int i = 42;

   public class B {
     public void incr() { ++i; }
   }
 }

Sınıf B(gerçekten adlandırılmış C$B) kullandığından i, derleyici bayt kodu doğrulayıcıyı geçecek şekilde Berişime izin veren sentetik bir erişimci yöntemi oluşturur C.i. Ne yazık ki, ClassLoadera'dan bir sınıf oluşturmanıza izin byte[]verdiği için, 'kavanozunda mühürlenmemişse mümkün olan' paketinde Cyeni bir sınıf oluşturarak iç sınıflara maruz kalan ayrıcalıklara ulaşmak oldukça basittir .CC

Doğru privateuygulama, sınıf yükleyicileri, bayt kodu doğrulayıcısı ve ayrıcalıklara yansıtıcı erişimi engelleyebilecek güvenlik politikası arasında koordinasyon gerektirir.


Bir sınıfın gizli durumunun saldırıya uğramasını önlemek için kullanılabilir mi?

Evet. Her biri modüllerinin güvenlik özelliklerini korurken programcılar birlikte çalışabildiklerinde "güvenli ayrışma" mümkündür - Modülümün güvenlik özelliklerini ihlal etmemesi için başka bir kod modülünün yazarına güvenmek zorunda değilim.

Joe-E gibi Nesne Yetenekleri dilleri , güvenli ayrışmayı mümkün kılmak için bilgi gizleme ve diğer yöntemleri kullanır:

Joe-E, nesne yetenekleri disiplinine göre güvenli programlamayı desteklemek için tasarlanmış Java programlama dilinin bir alt kümesidir. Joe-E, güvenli sistemlerin inşasını kolaylaştırmanın yanı sıra Joe-E'de yerleşik sistemlerin güvenlik incelemelerini kolaylaştırmayı amaçlamaktadır.

Bu sayfadan bağlanan makale, privateuygulamanın güvenli ayrışmayı nasıl mümkün kıldığına dair bir örnek vermektedir .

Güvenli kapsülleme sağlanması.

Şekil 1. Yalnızca ek bir günlük kaydı özelliği.

public final class Log {
  private final StringBuilder content;
  public Log() {
    content = new StringBuilder();
  }
  public void write(String s) {
    content.append(s);
  }
}

Bir kişinin salt eklenmiş bir günlük tesisini nasıl inşa edebileceğini gösteren Şekil 1'i düşünün. Programın geri kalanının Joe-E'de yazılması koşuluyla, bir kod inceleyici yalnızca günlük girişlerinin eklenebileceğini ve değiştirilemeyeceğini veya kaldırılamayacağını düşünebilir. Bu inceleme pratiktir, çünkü sadece Log sınıfın denetlenmesini gerektirir ve başka bir kodun gözden geçirilmesini gerektirmez. Sonuç olarak, bu özelliğin doğrulanması, günlük kodu hakkında yalnızca yerel gerekçe gerektirir.


1

Bilgi gizleme, iyi yazılım tasarımının temel endişelerinden biridir. Dave Parnas'ın 70'lerin sonlarındaki makalelerine göz atın. Temel olarak, modülünüzün dahili durumunun tutarlı olduğunu garanti edemezseniz, davranışı hakkında hiçbir şey garanti edemezsiniz. İçsel durumunu garanti etmenin tek yolu, onu özel tutmak ve yalnızca sağladığınız yöntemlerle değiştirilmesine izin vermektir.


1

Korumayı dilin bir parçası haline getirerek bir şey kazanırsınız: makul güvence.

Bir değişkeni özel yaparsam, yalnızca o sınıftaki kod veya o sınıfın açıkça bildirilen arkadaşları tarafından dokunacağına dair makul güvencem var. Bu değere makul şekilde dokunabilen kodun kapsamı sınırlıdır ve açıkça tanımlanmıştır.

Şimdi sözdizimsel korumayı aşmanın yolları var mı? Kesinlikle; çoğu dilde vardır. C ++ 'da, sınıfı her zaman başka bir türe atabilir ve bitlerine kurcalayabilirsiniz. Java ve C # 'da kendinizi buna yansıtabilirsiniz. Ve böylece.

Ancak, bunu yapmak zordur . Yapmamanız gereken bir şey yaptığınız açıktır. Sen olamaz kazara (C yabani yazma dışında ++) bunu. İsteyerek düşünmelisin, "Derleyicim tarafından bana söylenmeyen bir şeye dokunacağım." İsteyerek mantıksız bir şey yapmalısınız .

Sözdizimsel koruma olmadan, bir programcı yanlışlıkla bir şeyleri mahvedebilir. Kullanıcıya bir kural öğretmelisiniz ve her seferinde bu kurala uymaları gerekir . Eğer yapmazlarsa, dünya çok güvensiz hale gelir.

Sözdizimsel koruma olmadan, yanlış kişi üzerindedir: sınıfı kullanan birçok kişi. Sözleşmeyi takip etmelidirler yoksa belirtilmemiş kötülükler meydana gelecektir. Belirtilmemiş kötülük: O Çizilmeye olabilir oluşur.

Yanlış bir şey yaparsanız, her şey yine de işe yarayabilir bir API daha kötü bir şey yoktur. Bu, kullanıcıya doğru şeyi yaptıkları, her şeyin yolunda olduğu vb.

Peki bu dile yeni kullanıcılar ne olacak? Yalnızca gerçek sözdizimini (derleyici tarafından zorunlu kılınan) öğrenmek ve takip etmekle kalmazlar, şimdi de bu kurala uymalıdırlar (en iyi akranları tarafından uygulanır). Ve eğer yapmazlarsa, o zaman kötü bir şey olamaz. Bir programcı sözleşmenin neden var olduğunu anlamıyorsa ne olur? "Lanet olsun" dediğinde ve sadece sizin özelliğinize seslendiğinde ne olur? Ve her şey çalışmaya devam ederse ne düşünüyor?

Sözleşmenin aptal olduğunu düşünüyor. Ve bir daha asla takip etmeyecek. Ve tüm arkadaşlarına da rahatsız etmemelerini söyleyecek.

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.