Break OO privacy: Difference between revisions
m (→{{header|Java}}: correct mixed use of tabs and spaces) |
(Omit Zig) |
||
(14 intermediate revisions by 9 users not shown) | |||
Line 1: | Line 1: | ||
[[Category:Object oriented]] |
|||
{{ |
{{task}} |
||
{{omit from|BASIC}} |
|||
{{omit from|BBC BASIC}} |
|||
{{omit from|C}} |
|||
{{omit from|Déjà Vu}} |
|||
{{omit from|GUISS}} |
|||
{{omit from|Haskell}} |
|||
{{omit from|Locomotive Basic}} |
|||
{{omit from|Lotus 123 Macro Scripting}} |
|||
{{omit from|Mathematica}} |
|||
{{omit from|R}} |
|||
{{omit from|Rust}} |
|||
{{omit from|SmileBASIC}} |
|||
{{omit from|ZX Spectrum Basic}} |
|||
Show how to access private or protected members of a class in an object-oriented language from outside an instance of the class, without calling non-private or non-protected members of the class as a proxy. |
Show how to access private or protected members of a class in an object-oriented language from outside an instance of the class, without calling non-private or non-protected members of the class as a proxy. |
||
The intent is to show how a debugger, serializer, or other meta-programming tool might access information that is barred by normal access methods to the object but can nevertheless be accessed from within the language by some provided escape hatch or reflection mechanism. |
The intent is to show how a debugger, serializer, or other meta-programming tool might access information that is barred by normal access methods to the object but can nevertheless be accessed from within the language by some provided escape hatch or reflection mechanism. |
||
Line 22: | Line 8: | ||
as unidiomatic at best, and poor programming practice at worst. |
as unidiomatic at best, and poor programming practice at worst. |
||
Nonetheless, if your language intentionally maintains a double-standard for OO privacy, here's where you can show it off. |
Nonetheless, if your language intentionally maintains a double-standard for OO privacy, here's where you can show it off. |
||
=={{header|ABAP}}== |
=={{header|ABAP}}== |
||
Similar to C++, ABAP allows the declaration of friends which can be both classes and interfaces. All subclasses of friend classes are automatically friends of the source class. For example if classA (source) has classB as a friend and classC is a subclass of classB then classC is a friend of classA. Similarly all implementing classes of friend interfaces are friends of the source class. Also all interfaces which contain the befriended interface as a component are friends of the source class. |
Similar to C++, ABAP allows the declaration of friends which can be both classes and interfaces. All subclasses of friend classes are automatically friends of the source class. For example if classA (source) has classB as a friend and classC is a subclass of classB then classC is a friend of classA. Similarly all implementing classes of friend interfaces are friends of the source class. Also all interfaces which contain the befriended interface as a component are friends of the source class. |
||
< |
<syntaxhighlight lang="abap">class friendly_class definition deferred. |
||
class my_class definition friends friendly_class . |
class my_class definition friends friendly_class . |
||
Line 68: | Line 53: | ||
endclass. |
endclass. |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Ada}}== |
=={{header|Ada}}== |
||
One of the great criticisms of Pascal was "there is no escape". The reason was that sometimes you have to convert the incompatible. |
One of the great criticisms of Pascal was "there is no escape". The reason was that sometimes you have to convert the incompatible. We start with a package, which defines the data type which holds the secret. |
||
as breaking OO privacy. We start with the package that holds the "secret": |
|||
< |
<syntaxhighlight lang="ada">package OO_Privacy is |
||
type Confidential_Stuff is tagged private; |
type Confidential_Stuff is tagged private; |
||
Line 84: | Line 67: | ||
Password: Password_Type := "default!"; -- the "secret" |
Password: Password_Type := "default!"; -- the "secret" |
||
end record; |
end record; |
||
end OO_Privacy;</ |
end OO_Privacy;</syntaxhighlight> |
||
When we later define an object C of type Confidential_Stuff, we can't read read the password stored in C -- except by breaking / bypassing OO privacy rules. |
|||
Second, the package that provides the "hack" into Confidential_Stuff: |
|||
=== Using Unchecked_Conversion === |
|||
One way to read the password is by using the generic function Unchecked_Conversion: |
|||
<syntaxhighlight lang="ada">with OO_Privacy, Ada.Unchecked_Conversion, Ada.Text_IO; |
|||
procedure OO_Break_Privacy is |
procedure OO_Break_Privacy is |
||
Line 103: | Line 90: | ||
begin |
begin |
||
Ada.Text_IO.Put_Line("The secret password is """ & Hack(C).Password & """"); |
Ada.Text_IO.Put_Line("The secret password is """ & Hack(C).Password & """"); |
||
end OO_Break_Privacy;</ |
end OO_Break_Privacy;</syntaxhighlight> |
||
The output shows that C holds, surprise, surprise, the default password: |
The output shows that C holds, surprise, surprise, the default password: |
||
Line 109: | Line 96: | ||
<pre>The secret password is "default!"</pre> |
<pre>The secret password is "default!"</pre> |
||
=== Child Packages === |
|||
=={{header|C sharp}}== |
|||
<lang csharp>using System; |
|||
Another way to bypass privacy is using a child package. Ada child packages have access to their parents' private data structures (somewhat similar to "friends" in C++"): |
|||
<syntaxhighlight lang="ada">package OO_Privacy.Friend is -- child package of OO.Privacy |
|||
function Get_Password(Secret: Confidential_Stuff) return String; |
|||
end OO_Privacy.Friend;</syntaxhighlight> |
|||
<syntaxhighlight lang="ada">package body OO_Privacy.Friend is -- implementation of the child package |
|||
function Get_Password(Secret: Confidential_Stuff) return String is |
|||
(Secret.Password); |
|||
end OO_Privacy.Friend;</syntaxhighlight> |
|||
Now here is the program that uses the child package, to read the secret: |
|||
<syntaxhighlight lang="ada">with OO_Privacy.Friend, Ada.Text_IO; |
|||
procedure Bypass_OO_Privacy is |
|||
C: OO_Privacy.Confidential_Stuff; -- which password is hidden inside C? |
|||
begin |
|||
Ada.Text_IO.Put_Line("Password: """ & |
|||
OO_Privacy.Friend.Get_Password(C) & |
|||
""""); |
|||
end Bypass_OO_Privacy;</syntaxhighlight> |
|||
Once again, we have been too lazy to overwrite the default password: |
|||
<pre>Password: "default!"</pre> |
|||
In fact, the password has to be the default one, because we cannot change the password. For that purpose, we would have to write a setter procedure, and either include it in the package OO_Privacy, or in a child package of OO_Privacy. (Or we could use Unchecked_Conversion to overwrite the default password -- but that is bad style.) |
|||
=={{header|C sharp|C#}}== |
|||
<syntaxhighlight lang="csharp">using System; |
|||
using System.Reflection; |
using System.Reflection; |
||
Line 127: | Line 150: | ||
Console.WriteLine(answer); |
Console.WriteLine(answer); |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<lang>42</ |
<syntaxhighlight lang="text">42</syntaxhighlight> |
||
=={{header|C++}}== |
=={{header|C++}}== |
||
C++ has the 'friend' keyword to indicate that one class should have access to the private data of another. Here's a simple use case. (Please note that this code is not thread-safe.) |
C++ has the 'friend' keyword to indicate that one class should have access to the private data of another. Here's a simple use case. (Please note that this code is not thread-safe.) |
||
< |
<syntaxhighlight lang="cpp">#include <iostream> |
||
class CWidget; // Forward-declare that we have a class named CWidget. |
class CWidget; // Forward-declare that we have a class named CWidget. |
||
Line 201: | Line 223: | ||
delete pWidget3; |
delete pWidget3; |
||
delete pWidget2; |
delete pWidget2; |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
< |
<syntaxhighlight lang="text">Widget spawning. There are now 1 Widgets instanciated. |
||
Widget spawning. There are now 2 Widgets instanciated. |
Widget spawning. There are now 2 Widgets instanciated. |
||
Widget dieing. There are now 1 Widgets instanciated. |
Widget dieing. There are now 1 Widgets instanciated. |
||
Widget spawning. There are now 2 Widgets instanciated. |
Widget spawning. There are now 2 Widgets instanciated. |
||
Widget dieing. There are now 1 Widgets instanciated. |
Widget dieing. There are now 1 Widgets instanciated. |
||
Widget dieing. There are now 0 Widgets instanciated.</ |
Widget dieing. There are now 0 Widgets instanciated.</syntaxhighlight> |
||
Without the "friend" mechanism, it's still possible to meaningfully modify any member in another class, as long as you know that member's address in memory, and its type. Here's the same program as above, but using a pointer to m_uicount, rather a reference to the factory: |
Without the "friend" mechanism, it's still possible to meaningfully modify any member in another class, as long as you know that member's address in memory, and its type. Here's the same program as above, but using a pointer to m_uicount, rather a reference to the factory: |
||
< |
<syntaxhighlight lang="cpp">#include <iostream> |
||
class CWidget; // Forward-declare that we have a class named CWidget. |
class CWidget; // Forward-declare that we have a class named CWidget. |
||
Line 277: | Line 299: | ||
delete pWidget3; |
delete pWidget3; |
||
delete pWidget2; |
delete pWidget2; |
||
}</ |
}</syntaxhighlight> |
||
=={{header|Clojure}}== |
=={{header|Clojure}}== |
||
You can use the var-quote macro to get values from private variables. Here's an example of a variable 'priv' marked private in namespace 'a': |
You can use the var-quote macro to get values from private variables. Here's an example of a variable 'priv' marked private in namespace 'a': |
||
< |
<syntaxhighlight lang="clojure"> |
||
(ns a) |
(ns a) |
||
(def ^:private priv :secret) |
(def ^:private priv :secret) |
||
Line 289: | Line 310: | ||
user=> @#'a/priv ; succeeds |
user=> @#'a/priv ; succeeds |
||
:secret |
:secret |
||
</syntaxhighlight> |
|||
</lang> |
|||
Clojure can also access Java private variables with the same strategy that Java uses. As a convenience, use the [http://clojuredocs.org/clojure_contrib/clojure.contrib.reflect/get-field get-field] function from clojure.contrib.reflect. Here's an example of grabbing the private field "serialVersionUID" from java.lang.Double: |
Clojure can also access Java private variables with the same strategy that Java uses. As a convenience, use the [http://clojuredocs.org/clojure_contrib/clojure.contrib.reflect/get-field get-field] function from clojure.contrib.reflect. Here's an example of grabbing the private field "serialVersionUID" from java.lang.Double: |
||
< |
<syntaxhighlight lang="clojure"> |
||
user=> (get-field Double "serialVersionUID" (Double/valueOf 1.0)) |
user=> (get-field Double "serialVersionUID" (Double/valueOf 1.0)) |
||
-9172774392245257468 |
-9172774392245257468 |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Common Lisp}}== |
=={{header|Common Lisp}}== |
||
Line 312: | Line 332: | ||
A symbol can be present in more than one package, such that it can be internal in some of them, and external in others. |
A symbol can be present in more than one package, such that it can be internal in some of them, and external in others. |
||
< |
<syntaxhighlight lang="lisp">(defpackage :funky |
||
;; only these symbols are public |
;; only these symbols are public |
||
(:export :widget :get-wobbliness) |
(:export :widget :get-wobbliness) |
||
Line 356: | Line 376: | ||
;; even read and evaluated. The symbol is internal and so cannot be used. |
;; even read and evaluated. The symbol is internal and so cannot be used. |
||
(format t "wobbliness: ~a~%" (slot-value *w* 'funky:wobbliness)) |
(format t "wobbliness: ~a~%" (slot-value *w* 'funky:wobbliness)) |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{Out}} using CLISP: |
{{Out}} using CLISP: |
||
Line 364: | Line 384: | ||
*** - READ from #<INPUT BUFFERED FILE-STREAM CHARACTER #P"funky.lisp" @44>: |
*** - READ from #<INPUT BUFFERED FILE-STREAM CHARACTER #P"funky.lisp" @44>: |
||
#<PACKAGE FUNKY> has no external symbol with name "WOBBLINESS"</pre> |
#<PACKAGE FUNKY> has no external symbol with name "WOBBLINESS"</pre> |
||
=={{header|D}}== |
=={{header|D}}== |
||
Line 370: | Line 389: | ||
breakingprivacy.d: |
breakingprivacy.d: |
||
< |
<syntaxhighlight lang="d">module breakingprivacy; |
||
struct Foo |
struct Foo |
||
Line 380: | Line 399: | ||
string str; |
string str; |
||
float f; |
float f; |
||
}</ |
}</syntaxhighlight> |
||
app.d: |
app.d: |
||
< |
<syntaxhighlight lang="d">import std.stdio; |
||
import breakingprivacy; |
import breakingprivacy; |
||
Line 398: | Line 417: | ||
__traits(getMember, foo, "str") = "Not so private anymore!"; |
__traits(getMember, foo, "str") = "Not so private anymore!"; |
||
writeln("Modified foo: ", foo); |
writeln("Modified foo: ", foo); |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
< |
<syntaxhighlight lang="text">Foo([1, 2, 3], 42, "Hello World!", 3.14) |
||
foo.x = 42 |
foo.x = 42 |
||
Modified foo: Foo([1, 2, 3], 42, "Not so private anymore!", 3.14)</ |
Modified foo: Foo([1, 2, 3], 42, "Not so private anymore!", 3.14)</syntaxhighlight> |
||
=={{header|E}}== |
=={{header|E}}== |
||
Line 410: | Line 428: | ||
{{improve|E|Show an example of such an evaluator once it is available.}} |
{{improve|E|Show an example of such an evaluator once it is available.}} |
||
=={{header|Ecstasy}}== |
|||
In Ecstasy, using the keywords <span style="background-color: #e5e4e2"><tt> public </tt></span>, <span style="background-color: #e5e4e2"><tt> protected </tt></span>, and <span style="background-color: #e5e4e2"><tt> private </tt></span> to mark classes and class members is solely for the benefit of the developer, and not in any way related to security. These keywords help the developer to classify information among three categories: Things that are useful to everyone; things that are useful to further compositions (such as sub-classes and mixins); and things that, were they exposed, would likely to create an ugly mess. <b>Information hiding is about organization, and not about security.</b> |
|||
An Ecstasy reference contains both its type (the type of the <i>reference</i> itself, as opposed to the type of the referred-to object, a.k.a. the <i>referent</i>), and the means -- a "pointer" or a "value" -- to refer to the referent. By default, the type of a reference is of the <i>public type</i> of the referent, but it is possible to reveal the referent as any other legal type -- where <i>legal</i> simply means that strong type safety is enforced. This is <b>not</b> a type cast; it is a request to the runtime to provide a different reference to the same underlying object. |
|||
Ecstasy security is accomplished by the use of <i>software containers</i>. Code running in a container is always allowed reveal any legal type on any object created within that container, including any object created within sub-containers. However, the runtime will reject any reveal request on any object that was <i>not</i> created within that container. |
|||
<syntaxhighlight lang="java"> |
|||
module BreakOO { |
|||
/** |
|||
* This is a class with public, protected, and private properties. |
|||
*/ |
|||
class Exposed { |
|||
public String pub = "public"; |
|||
protected String pro = "protected"; |
|||
private String pri = "private"; |
|||
@Override |
|||
String toString() { |
|||
return $"pub={pub.quoted()}, pro={pro.quoted()}, pri={pri.quoted()}"; |
|||
} |
|||
} |
|||
void run() { |
|||
@Inject Console console; |
|||
Exposed expo = new Exposed(); |
|||
console.print($"before: {expo}"); |
|||
// you can only access public members from the default reference |
|||
expo.pub = $"this was {expo.pub}"; |
|||
// expo.pro = $"this was {expo.pro}"; <- compiler error |
|||
// expo.pri = $"this was {expo.pri}"; <- compiler error |
|||
// but you can ask for the protected reference ... |
|||
assert (protected Exposed) expoPro := &expo.revealAs((protected Exposed)); |
|||
expoPro.pro = $"this was {expoPro.pro}"; |
|||
// expoPro.pri = $"this was {expoPro.pri}"; <- compiler error |
|||
// and you can ask for the private reference ... |
|||
assert (private Exposed) expoPri := &expo.revealAs((private Exposed)); |
|||
expoPri.pri = $"this was {expoPri.pri}"; |
|||
// or you can ask for the underlying struct, which is a passive |
|||
// object that contains only the field storage |
|||
assert (struct Exposed) expoStr := &expo.revealAs((struct Exposed)); |
|||
expoStr.pub = $"{expoStr.pub}!!!"; |
|||
expoStr.pro = $"{expoStr.pro}!!!"; |
|||
expoStr.pri = $"{expoStr.pri}!!!"; |
|||
console.print($"after: {expo}"); |
|||
} |
|||
} |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
before: pub="public", pro="protected", pri="private" |
|||
after: pub="this was public!!!", pro="this was protected!!!", pri="this was private!!!" |
|||
</pre> |
|||
=={{header|F_Sharp|F#}}== |
=={{header|F_Sharp|F#}}== |
||
{{trans|C#}} |
{{trans|C#}} |
||
< |
<syntaxhighlight lang="fsharp">open System |
||
open System.Reflection |
open System.Reflection |
||
Line 428: | Line 506: | ||
let answer = fieldInfo.GetValue(myInstance) |
let answer = fieldInfo.GetValue(myInstance) |
||
printfn "%s = %A" (answer.GetType().ToString()) answer |
printfn "%s = %A" (answer.GetType().ToString()) answer |
||
0</ |
0</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>System.Int32 = 42</pre> |
<pre>System.Int32 = 42</pre> |
||
=={{header|Factor}}== |
=={{header|Factor}}== |
||
From the [http://docs.factorcode.org/content/article-word-search-private.html documentation for private words]: ''"Privacy is not enforced by the system; private words can be called from other vocabularies, and from the listener. However, this should be avoided where possible."'' |
From the [http://docs.factorcode.org/content/article-word-search-private.html documentation for private words]: ''"Privacy is not enforced by the system; private words can be called from other vocabularies, and from the listener. However, this should be avoided where possible."'' |
||
Line 437: | Line 514: | ||
This example uses the private word ''sequence/tester'' from the vocabulary ''sets.private''. It tries to count the elements in an intersection of two sets. |
This example uses the private word ''sequence/tester'' from the vocabulary ''sets.private''. It tries to count the elements in an intersection of two sets. |
||
< |
<syntaxhighlight lang="factor">( scratchpad ) USING: sets sets.private ; |
||
( scratchpad ) { 1 2 3 } { 1 2 4 } sequence/tester count . |
( scratchpad ) { 1 2 3 } { 1 2 4 } sequence/tester count . |
||
2</ |
2</syntaxhighlight> |
||
There is better way to do the same, without any private words. |
There is better way to do the same, without any private words. |
||
< |
<syntaxhighlight lang="factor">( scratchpad ) USE: sets |
||
( scratchpad ) { 1 2 3 } { 1 2 4 } intersect length . |
( scratchpad ) { 1 2 3 } { 1 2 4 } intersect length . |
||
2</ |
2</syntaxhighlight> |
||
=={{header|Forth}}== |
=={{header|Forth}}== |
||
{{works with|Forth}} |
{{works with|Forth}} |
||
Line 453: | Line 529: | ||
Needs the FMS-SI (single inheritance) library code located here: |
Needs the FMS-SI (single inheritance) library code located here: |
||
http://soton.mpeforth.com/flag/fms/index.html |
http://soton.mpeforth.com/flag/fms/index.html |
||
< |
<syntaxhighlight lang="forth">include FMS-SI.f |
||
99 value x \ create a global variable named x |
99 value x \ create a global variable named x |
||
Line 470: | Line 546: | ||
50 .. f1.x ! \ use the dot parser to access the private x without a message |
50 .. f1.x ! \ use the dot parser to access the private x without a message |
||
f1 print \ 50 |
f1 print \ 50 |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|FreeBASIC}}== |
=={{header|FreeBASIC}}== |
||
FreeBASIC generally does a good job of maintaining OO privacy as it doesn't support reflection and even its OffsetOf keyword cannot obtain the offset within a user defined type of a private or protected field. You therefore have to guess the offset of a non-public field in order to be able to access it using a raw pointer though this is not generally a difficult task. |
FreeBASIC generally does a good job of maintaining OO privacy as it doesn't support reflection and even its OffsetOf keyword cannot obtain the offset within a user defined type of a private or protected field. You therefore have to guess the offset of a non-public field in order to be able to access it using a raw pointer though this is not generally a difficult task. |
||
However, as usual, macros come to the rescue and one can easily access non-public members by the simple expedient (or, if you prefer, 'dirty hack') of redefining the Private and Protected keywords to mean Public: |
However, as usual, macros come to the rescue and one can easily access non-public members by the simple expedient (or, if you prefer, 'dirty hack') of redefining the Private and Protected keywords to mean Public: |
||
< |
<syntaxhighlight lang="freebasic">'FB 1.05.0 Win64 |
||
#Undef Private |
#Undef Private |
||
Line 496: | Line 571: | ||
Print |
Print |
||
Print "Press any key to quit" |
Print "Press any key to quit" |
||
Sleep</ |
Sleep</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 502: | Line 577: | ||
1 2 3 |
1 2 3 |
||
</pre> |
</pre> |
||
=={{header|Go}}== |
=={{header|Go}}== |
||
Go has a <code>reflect</code> and <code>unsafe</code> package that together can do this. |
Go has a <code>reflect</code> and <code>unsafe</code> package that together can do this. |
||
Line 509: | Line 583: | ||
A relevant Go Blog article is |
A relevant Go Blog article is |
||
[http://blog.golang.org/laws-of-reflection The Laws of Reflection]. |
[http://blog.golang.org/laws-of-reflection The Laws of Reflection]. |
||
< |
<syntaxhighlight lang="go">package main |
||
import ( |
import ( |
||
Line 596: | Line 670: | ||
_, err := r.ReadByte() |
_, err := r.ReadByte() |
||
fmt.Println("bufio.ReadByte returned error:", err) |
fmt.Println("bufio.ReadByte returned error:", err) |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 612: | Line 686: | ||
==Icon and {{header|Unicon}}== |
==Icon and {{header|Unicon}}== |
||
{{omit from|Icon}} |
|||
Unicon implements object environments with records and supporting procedures for creation, initialization, and methods. The variables in the class environment can be accessed like any other record field. Additionally, with the ''fieldnames'' procedure you can obtain the names of the class variables. |
Unicon implements object environments with records and supporting procedures for creation, initialization, and methods. The variables in the class environment can be accessed like any other record field. Additionally, with the ''fieldnames'' procedure you can obtain the names of the class variables. |
||
Line 618: | Line 691: | ||
Note: Unicon can be translated via a command line switch into icon which allows for classes to be shared with Icon code (assuming no other incompatibilities exist). |
Note: Unicon can be translated via a command line switch into icon which allows for classes to be shared with Icon code (assuming no other incompatibilities exist). |
||
< |
<syntaxhighlight lang="unicon">link printf |
||
procedure main() |
procedure main() |
||
Line 634: | Line 707: | ||
printf("foo var1=%i, var2=%i, var3=%i\n",var1,var2,var3) |
printf("foo var1=%i, var2=%i, var3=%i\n",var1,var2,var3) |
||
end |
end |
||
end</ |
end</syntaxhighlight> |
||
{{libheader|Icon Programming Library}} |
{{libheader|Icon Programming Library}} |
||
Line 643: | Line 716: | ||
var 1 of foo x = 1 |
var 1 of foo x = 1 |
||
foo var1=-1, var2=2, var3=3</pre> |
foo var1=-1, var2=2, var3=3</pre> |
||
=={{header|J}}== |
=={{header|J}}== |
||
Line 651: | Line 723: | ||
J does support a "[http://www.jsoftware.com/help/dictionary/dx003.htm Lock Script]" mechanism - to transform a J script so that it's unreadable. However, anyone with access to a machine running the code and ordinary developer tools or who understands the "locking" technique could unlock it. |
J does support a "[http://www.jsoftware.com/help/dictionary/dx003.htm Lock Script]" mechanism - to transform a J script so that it's unreadable. However, anyone with access to a machine running the code and ordinary developer tools or who understands the "locking" technique could unlock it. |
||
=={{header|Java}}== |
=={{header|Java}}== |
||
<p> |
|||
Private fields (and in general all members) of a Java class can be accessed via reflection, but must pass a security check in order to do so. There are two such security checks, one for discovering the field at all, and another for granting access to it in order to be able to read and write it. (This in turn means that trusted applications can do this — it is in fact a mechanism used by important frameworks like Spring — but untrusted applets cannot.) |
|||
In order the access a class member of another class which is marked as <code>private</code>, you'll need to use <kbd>reflection</kbd>.<br /> |
|||
<lang java>import java.lang.reflect.*; |
|||
Java offers a collection of <kbd>reflection</kbd>-related utilities within the <code>java.lang.reflect</code> package. |
|||
</p> |
|||
<p> |
|||
In this example I'll use a class with two fields, <code>stringA</code> and <code>stringB</code>. |
|||
</p> |
|||
<syntaxhighlight lang="java"> |
|||
class Example { |
class Example { |
||
String stringA = "rosetta"; |
|||
private String stringB = "code"; |
|||
public Example(String name) { _name = name; } |
|||
public String toString() { return "Hello, I am " + _name; } |
|||
} |
} |
||
</syntaxhighlight> |
|||
<p> |
|||
public class BreakPrivacy { |
|||
From another class, I'll instantiate <code>Example</code>, and use a <code>Field</code> object to return a specified, declared field.<br /> |
|||
public static final void main(String[] args) throws Exception { |
|||
To do this you call the <code>getDeclaredField</code> on your <code>Class</code> object, supplying the <kbd>name</kbd> of the field. |
|||
Example foo = new Example("Eric"); |
|||
</p> |
|||
<syntaxhighlight lang="java"> |
|||
for (Field f : Example.class.getDeclaredFields()) { |
|||
Example example = new Example(); |
|||
if (f.getName().equals("_name")) { |
|||
Field field = example.getClass().getDeclaredField("stringB"); |
|||
// make it accessible |
|||
</syntaxhighlight> |
|||
f.setAccessible(true); |
|||
<p> |
|||
To allow access to <code>stringB</code> we'll need to use the <code>Field.setAccessible</code> method, and signify <kbd>true</kbd>.<br /> |
|||
// get private field |
|||
This is essentially what the task is looking for, the ability to override the <kbd>access-modifier</kbd>. |
|||
System.out.println(f.get(foo)); |
|||
</p> |
|||
<syntaxhighlight lang="java"> |
|||
// set private field |
|||
field.setAccessible(true); |
|||
f.set(foo, "Edith"); |
|||
</syntaxhighlight> |
|||
System.out.println(foo); |
|||
<p> |
|||
Now, we can access the data from the field by using the <code>Field.get</code> method, specifying the instance as the parameter. |
|||
break; |
|||
</p> |
|||
} |
|||
<syntaxhighlight lang="java"> |
|||
} |
|||
String stringB = (String) field.get(example); |
|||
} |
|||
</syntaxhighlight> |
|||
}</lang> |
|||
<p> |
|||
{{out}} |
|||
So, all together our method would contain the following lines. |
|||
</p> |
|||
<syntaxhighlight lang="java"> |
|||
Example example = new Example(); |
|||
Field field = example.getClass().getDeclaredField("stringB"); |
|||
field.setAccessible(true); |
|||
String stringA = example.stringA; |
|||
String stringB = (String) field.get(example); |
|||
System.out.println(stringA + " " + stringB); |
|||
</syntaxhighlight> |
|||
<p> |
|||
With an output of the following. |
|||
</p> |
|||
<pre> |
<pre> |
||
rosetta code |
|||
Eric |
|||
Hello, I am Edith |
|||
</pre> |
</pre> |
||
<p> |
|||
All classes are vulnerable to this, including <code>String</code> (and therefore, string literals). How long is the word "cat"? |
|||
If we hadn't used the <code>Field.setAccessible</code> method, we would get an <code>IllegalAccessException</code>. |
|||
</p> |
|||
<pre> |
|||
cannot access a member of class Example with modifiers "private" |
|||
</pre> |
|||
<p> |
|||
Additionally, you can do this with methods via the <code>Method</code> object.<br /> |
|||
Consider the following class. |
|||
</p> |
|||
<syntaxhighlight lang="java"> |
|||
class Example { |
|||
String stringA = "rosetta"; |
|||
private String stringB() { |
|||
(Note: somewhere between Java 8 and Java 11 this stopped working because the <code>value</code> field of <code>String</code> is <code>final</code>. The reflective access is still possible, but changing a final field isn't.) |
|||
return "code"; |
|||
<lang Java>import java.lang.reflect.*; |
|||
} |
|||
public class BreakString{ |
|||
public static void main(String... args) throws Exception{ |
|||
Field f = String.class.getDeclaredField("value"); |
|||
f.setAccessible(true); |
|||
f.set("cat",new char[]{'t','i','g','e','r'}); |
|||
System.out.println("cat"); |
|||
System.out.println("cat".length()); |
|||
} |
|||
} |
} |
||
</syntaxhighlight> |
|||
</lang> |
|||
<p> |
|||
{{out}} |
|||
The approach is the same, except we are using <code>getDeclaredMethod</code>, and instead of <code>get</code> we are using <code>invoke</code>. |
|||
</p> |
|||
<syntaxhighlight lang="java"> |
|||
Example example = new Example(); |
|||
Method method = example.getClass().getDeclaredMethod("stringB"); |
|||
method.setAccessible(true); |
|||
String stringA = example.stringA; |
|||
String stringB = (String) method.invoke(example); |
|||
System.out.println(stringA + " " + stringB); |
|||
</syntaxhighlight> |
|||
<pre> |
<pre> |
||
rosetta code |
|||
tiger |
|||
5 |
|||
</pre> |
</pre> |
||
Line 711: | Line 812: | ||
Julia's object model is one of structs which contain data and methods which are just functions using those structs, with multiple dispatch, rather than object methods, used to distinguish similarly named calls for different object types. Julia does not therefore enforce any private fields in its structures, since, except for constructors, it does not distinguish object methods from other functions. If private fields or methods are actually needed they can be kept from view by placing them inside a module which cannot be directly accessed by user code, such as in a module within a module. |
Julia's object model is one of structs which contain data and methods which are just functions using those structs, with multiple dispatch, rather than object methods, used to distinguish similarly named calls for different object types. Julia does not therefore enforce any private fields in its structures, since, except for constructors, it does not distinguish object methods from other functions. If private fields or methods are actually needed they can be kept from view by placing them inside a module which cannot be directly accessed by user code, such as in a module within a module. |
||
=={{header|Kotlin}}== |
=={{header|Kotlin}}== |
||
For tasks such as this, reflection is your friend: |
For tasks such as this, reflection is your friend: |
||
< |
<syntaxhighlight lang="scala">import kotlin.reflect.full.declaredMemberProperties |
||
import kotlin.reflect.jvm.isAccessible |
import kotlin.reflect.jvm.isAccessible |
||
Line 729: | Line 829: | ||
println("${prop.name} -> ${prop.get(tbb)}") |
println("${prop.name} -> ${prop.get(tbb)}") |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 735: | Line 835: | ||
secret -> 42 |
secret -> 42 |
||
</pre> |
</pre> |
||
=={{header|Logtalk}}== |
=={{header|Logtalk}}== |
||
Logtalk provides a ''context switching call'' control construct that allows a call to be executed as from within an object. It's mainly used for debugging and for writing unit tests. This control construct can be disabled on a global or per object basis to prevent it of being used to break encapsulation. |
Logtalk provides a ''context switching call'' control construct that allows a call to be executed as from within an object. It's mainly used for debugging and for writing unit tests. This control construct can be disabled on a global or per object basis to prevent it of being used to break encapsulation. |
||
In the following example, a prototype is used for simplicity. |
In the following example, a prototype is used for simplicity. |
||
< |
<syntaxhighlight lang="logtalk">:- object(foo). |
||
% be sure that context switching calls are allowed |
% be sure that context switching calls are allowed |
||
Line 751: | Line 850: | ||
bar(3). |
bar(3). |
||
:- end_object.</ |
:- end_object.</syntaxhighlight> |
||
After compiling and loading the above object, we can use the following query to access the private method: |
After compiling and loading the above object, we can use the following query to access the private method: |
||
< |
<syntaxhighlight lang="logtalk">| ?- foo<<bar(X). |
||
X = 1 ; |
X = 1 ; |
||
X = 2 ; |
X = 2 ; |
||
X = 3 |
X = 3 |
||
true</ |
true</syntaxhighlight> |
||
=={{header|Lua}}== |
|||
Lua doesn't have a native concept of classes, and the only custom data structure available is the table (in which all fields are always public). |
|||
However, it's pretty common for table/object creation functions in object-oriented code to return instances of other functions that uses local variables through lexical scoping, or their closure, which is not accessible to the outside code and could be considered a space with "private" fields. |
|||
These can be accessed indirectly through the [https://www.lua.org/manual/5.1/manual.html#5.9 debug library]. |
|||
<syntaxhighlight lang="lua">local function Counter() |
|||
-- These two variables are "private" to this function and can normally |
|||
-- only be accessed from within this scope, including by any function |
|||
-- created inside here. |
|||
local counter = {} |
|||
local count = 0 |
|||
function counter:increment() |
|||
-- 'count' is an upvalue here and can thus be accessed through the |
|||
-- debug library, as long as we have a reference to this function. |
|||
count = count + 1 |
|||
end |
|||
return counter |
|||
end |
|||
-- Create a counter object and try to access the local 'count' variable. |
|||
local counter = Counter() |
|||
for i = 1, math.huge do |
|||
local name, value = debug.getupvalue(counter.increment, i) |
|||
if not name then break end -- No more upvalues. |
|||
if name == "count" then |
|||
print("Found 'count', which is "..tostring(value)) |
|||
-- If the 'counter.increment' function didn't access 'count' |
|||
-- directly then we would never get here. |
|||
break |
|||
end |
|||
end</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Found 'count', which is 0 |
|||
</pre> |
|||
Note that there's an infinite number of other more complex ways for functions to store values in a "private" manner, and the introspection functionality of the debug library can only get you so far. |
|||
=={{header|M2000 Interpreter}}== |
=={{header|M2000 Interpreter}}== |
||
We want to read two private variables, and change values without using a public method (a module or a function), and without attach a temporary method (we can do that in M2000). There is a variant in READ statemend to set references from group members (for variables and arrays, and objects) to names with a reference for each. So using these names (here in the exaample K, M) we can read and write private variables. |
We want to read two private variables, and change values without using a public method (a module or a function), and without attach a temporary method (we can do that in M2000). There is a variant in READ statemend to set references from group members (for variables and arrays, and objects) to names with a reference for each. So using these names (here in the exaample K, M) we can read and write private variables. |
||
<syntaxhighlight lang="m2000 interpreter"> |
|||
<lang M2000 Interpreter> |
|||
Module CheckIt { |
Module CheckIt { |
||
Group Alfa { |
Group Alfa { |
||
Line 782: | Line 923: | ||
} |
} |
||
CheckIt |
CheckIt |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Nim}}== |
=={{header|Nim}}== |
||
File oo.nim: |
File oo.nim: |
||
< |
<syntaxhighlight lang="nim">type Foo* = object |
||
a: string |
a: string |
||
b: string |
b: string |
||
Line 792: | Line 932: | ||
proc createFoo*(a, b, c): Foo = |
proc createFoo*(a, b, c): Foo = |
||
Foo(a: a, b: b, c: c)</ |
Foo(a: a, b: b, c: c)</syntaxhighlight> |
||
By not adding a <code>*</code> to <code>Foo</code>'s members we don't export them. When we import this module we can't use them directly: |
By not adding a <code>*</code> to <code>Foo</code>'s members we don't export them. When we import this module we can't use them directly: |
||
< |
<syntaxhighlight lang="nim">var x = createFoo("this a", "this b", 12) |
||
echo x.a # compile time error</ |
echo x.a # compile time error</syntaxhighlight> |
||
The easiest way to get a debug view of any data: |
The easiest way to get a debug view of any data: |
||
<lang |
<syntaxhighlight lang="nim">echo repr(x)</syntaxhighlight> |
||
Output: |
Output: |
||
<pre>[a = 0x7f6bb87a7050"this a", |
<pre>[a = 0x7f6bb87a7050"this a", |
||
Line 804: | Line 944: | ||
c = 12]</pre> |
c = 12]</pre> |
||
More fine-grained: |
More fine-grained: |
||
< |
<syntaxhighlight lang="nim">import typeinfo |
||
for key, val in fields(toAny(x)): |
for key, val in fields(toAny(x)): |
||
Line 814: | Line 954: | ||
echo " is an integer with value: ", val.getBiggestInt |
echo " is an integer with value: ", val.getBiggestInt |
||
else: |
else: |
||
echo " is an unknown with value: ", val.repr</ |
echo " is an unknown with value: ", val.repr</syntaxhighlight> |
||
Output: |
Output: |
||
<pre>Key a |
<pre>Key a |
||
Line 822: | Line 962: | ||
Key c |
Key c |
||
is an integer with value: 12</pre> |
is an integer with value: 12</pre> |
||
=={{header|Objective-C}}== |
=={{header|Objective-C}}== |
||
In older versions of the compiler, you can simply access a private field from outside of the class. The compiler will give a warning, but you can ignore it and it will still compile. However, in current compiler versions it is now a hard compile error. |
In older versions of the compiler, you can simply access a private field from outside of the class. The compiler will give a warning, but you can ignore it and it will still compile. However, in current compiler versions it is now a hard compile error. |
||
Line 829: | Line 968: | ||
One solution is to use Key-Value Coding. It treats properties and instance variables as "keys" that you can get and set using key-value coding methods. |
One solution is to use Key-Value Coding. It treats properties and instance variables as "keys" that you can get and set using key-value coding methods. |
||
< |
<syntaxhighlight lang="objc">#import <Foundation/Foundation.h> |
||
@interface Example : NSObject { |
@interface Example : NSObject { |
||
Line 864: | Line 1,003: | ||
} |
} |
||
return 0; |
return 0; |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 874: | Line 1,013: | ||
Another solution is to use a category to add methods to the class (you can have categories in your code modify any class, even classes compiled by someone else, including system classes). Since the new method is in the class, it can use the class's private instance variables with no problem. |
Another solution is to use a category to add methods to the class (you can have categories in your code modify any class, even classes compiled by someone else, including system classes). Since the new method is in the class, it can use the class's private instance variables with no problem. |
||
< |
<syntaxhighlight lang="objc">#import <Foundation/Foundation.h> |
||
@interface Example : NSObject { |
@interface Example : NSObject { |
||
Line 923: | Line 1,062: | ||
} |
} |
||
return 0; |
return 0; |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 933: | Line 1,072: | ||
Finally, you can access the instance variable directly using runtime functions. |
Finally, you can access the instance variable directly using runtime functions. |
||
< |
<syntaxhighlight lang="objc">#import <Foundation/Foundation.h> |
||
#import <objc/runtime.h> |
#import <objc/runtime.h> |
||
Line 970: | Line 1,109: | ||
} |
} |
||
return 0; |
return 0; |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 976: | Line 1,115: | ||
Hello, I am Edith |
Hello, I am Edith |
||
</pre> |
</pre> |
||
=={{header|OCaml}}== |
=={{header|OCaml}}== |
||
Line 987: | Line 1,125: | ||
The reader is advised to stop reading here. |
The reader is advised to stop reading here. |
||
< |
<syntaxhighlight lang="ocaml">class point x y = |
||
object |
object |
||
val mutable x = x |
val mutable x = x |
||
Line 1,019: | Line 1,157: | ||
Printf.printf "Broken coord: (%d, %d)\n" x y; |
Printf.printf "Broken coord: (%d, %d)\n" x y; |
||
evil_reset p |
evil_reset p |
||
p#print</ |
p#print</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 1,027: | Line 1,165: | ||
Broken coord: (-1, -1) |
Broken coord: (-1, -1) |
||
(0, 0)</pre> |
(0, 0)</pre> |
||
=={{header|Oforth}}== |
=={{header|Oforth}}== |
||
Line 1,033: | Line 1,170: | ||
There is no other way to access attributes values from outside but to call methods on the object. |
There is no other way to access attributes values from outside but to call methods on the object. |
||
=={{header|Perl}}== |
=={{header|Perl}}== |
||
Perl's object model does not enforce privacy. An object is just a blessed reference, and a blessed reference can be dereferenced just like an ordinary reference. |
Perl's object model does not enforce privacy. An object is just a blessed reference, and a blessed reference can be dereferenced just like an ordinary reference. |
||
< |
<syntaxhighlight lang="perl">package Foo; |
||
sub new { |
sub new { |
||
my $class = shift; |
my $class = shift; |
||
Line 1,050: | Line 1,186: | ||
package main; |
package main; |
||
my $foo = Foo->new(); |
my $foo = Foo->new(); |
||
print "$_\n" for $foo->get_bar(), $foo->{_bar};</ |
print "$_\n" for $foo->get_bar(), $foo->{_bar};</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>I am ostensibly private |
<pre>I am ostensibly private |
||
I am ostensibly private</pre> |
I am ostensibly private</pre> |
||
=={{header|Phix}}== |
=={{header|Phix}}== |
||
{{libheader|Phix/Class}} |
{{libheader|Phix/Class}} |
||
Line 1,060: | Line 1,195: | ||
We can easily break that privacy mechanism via low-level routines with the required simulated/fake context,<br> |
We can easily break that privacy mechanism via low-level routines with the required simulated/fake context,<br> |
||
and at the same time be reasonably confident that no-one is ever going to manage to achieve that by accident. |
and at the same time be reasonably confident that no-one is ever going to manage to achieve that by accident. |
||
<!--<syntaxhighlight lang="phix">(notonline)--> |
|||
Needs 0.8.1+ |
|||
<span style="color: #008080;">without</span> <span style="color: #008080;">js</span> <span style="color: #000080;font-style:italic;">-- (no class under p2js)</span> |
|||
<lang Phix>class test |
|||
<span style="color: #008080;">class</span> <span style="color: #000000;">test</span> |
|||
private string msg = "this is a test" |
|||
<span style="color: #008080;">private</span> <span style="color: #004080;">string</span> <span style="color: #000000;">msg</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"this is a test"</span> |
|||
procedure show() ?this.msg end procedure |
|||
<span style="color: #008080;">procedure</span> <span style="color: #000000;">show</span><span style="color: #0000FF;">()</span> <span style="color: #0000FF;">?</span><span style="color: #7060A8;">this</span><span style="color: #0000FF;">.</span><span style="color: #000000;">msg</span> <span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span> |
|||
end class |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">class</span> |
|||
test t = new() |
|||
<span style="color: #000000;">test</span> <span style="color: #000000;">t</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">new</span><span style="color: #0000FF;">()</span> |
|||
t.show() |
|||
<span style="color: #000000;">t</span><span style="color: #0000FF;">.</span><span style="color: #000000;">show</span><span style="color: #0000FF;">()</span> |
|||
--?t.msg -- illegal |
|||
--t.msg |
<span style="color: #000080;font-style:italic;">--?t.msg -- illegal |
||
--t.msg = "this is broken" -- illegal</span> |
|||
include builtins\structs.e as structs |
|||
<span style="color: #008080;">include</span> <span style="color: #000000;">builtins</span><span style="color: #0000FF;">\</span><span style="color: #000000;">structs</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span> <span style="color: #008080;">as</span> <span style="color: #000000;">structs</span> |
|||
constant ctx = routine_id("test") -- magic/context |
|||
<span style="color: #008080;">constant</span> <span style="color: #000000;">ctx</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">routine_id</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"test"</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- magic/context |
|||
--constant ctx = "test" -- also works |
|||
--constant ctx = test |
--constant ctx = "test" -- also works |
||
--constant ctx = test -- also works</span> |
|||
?structs:fetch_field(t,"msg",ctx)&" (with some magic)" |
|||
<span style="color: #0000FF;">?</span><span style="color: #000000;">structs</span><span style="color: #0000FF;">:</span><span style="color: #000000;">fetch_field</span><span style="color: #0000FF;">(</span><span style="color: #000000;">t</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"msg"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ctx</span><span style="color: #0000FF;">)&</span><span style="color: #008000;">" (with some magic)"</span> |
|||
structs:store_field(t,"msg","this breaks privacy",ctx) |
|||
<span style="color: #000000;">structs</span><span style="color: #0000FF;">:</span><span style="color: #000000;">store_field</span><span style="color: #0000FF;">(</span><span style="color: #000000;">t</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"msg"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"this breaks privacy"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ctx</span><span style="color: #0000FF;">)</span> |
|||
t.show()</lang> |
|||
<span style="color: #000000;">t</span><span style="color: #0000FF;">.</span><span style="color: #000000;">show</span><span style="color: #0000FF;">()</span> |
|||
<!--</syntaxhighlight>--> |
|||
<small>(Obviously you could inline the ctx values rather than create a separate constant.)</small> |
<small>(Obviously you could inline the ctx values rather than create a separate constant.)</small> |
||
{{out}} |
{{out}} |
||
Line 1,083: | Line 1,220: | ||
"this breaks privacy" |
"this breaks privacy" |
||
</pre> |
</pre> |
||
=={{header|PHP}}== |
=={{header|PHP}}== |
||
While normally accessing private variables causes fatal errors, it's possible to catch output of some debugging functions and use it. Known functions which can get private variables include: <code>var_dump()</code>, <code>print_r()</code>, <code>var_export()</code> and <code>serialize()</code>. The easiest to use is <code>var_export()</code> because it's both valid PHP code and doesn't recognize private and public variables. |
While normally accessing private variables causes fatal errors, it's possible to catch output of some debugging functions and use it. Known functions which can get private variables include: <code>var_dump()</code>, <code>print_r()</code>, <code>var_export()</code> and <code>serialize()</code>. The easiest to use is <code>var_export()</code> because it's both valid PHP code and doesn't recognize private and public variables. |
||
{{works with|PHP|5.1}} |
{{works with|PHP|5.1}} |
||
< |
<syntaxhighlight lang="php"><?php |
||
class SimpleClass { |
class SimpleClass { |
||
private $answer = "hello\"world\nforever :)"; |
private $answer = "hello\"world\nforever :)"; |
||
Line 1,106: | Line 1,242: | ||
$new_class = eval($class_content); |
$new_class = eval($class_content); |
||
echo $new_class['answer'];</ |
echo $new_class['answer'];</syntaxhighlight> |
||
Another way commonly used to access private and protected variables in PHP is to cast the object to an array. It's probably unintentional though looking on how casted array contains null bytes (probably "private" mark). This works unless a magic method for the cast operation is implemented: |
Another way commonly used to access private and protected variables in PHP is to cast the object to an array. It's probably unintentional though looking on how casted array contains null bytes (probably "private" mark). This works unless a magic method for the cast operation is implemented: |
||
Line 1,112: | Line 1,248: | ||
{{works with|PHP|4.x}} |
{{works with|PHP|4.x}} |
||
{{works with|PHP|5.x}} |
{{works with|PHP|5.x}} |
||
< |
<syntaxhighlight lang="php"><?php |
||
class SimpleClass { |
class SimpleClass { |
||
private $answer = 42; |
private $answer = 42; |
||
Line 1,119: | Line 1,255: | ||
$class = new SimpleClass; |
$class = new SimpleClass; |
||
$classvars = (array)$class; |
$classvars = (array)$class; |
||
echo $classvars["\0SimpleClass\0answer"];</ |
echo $classvars["\0SimpleClass\0answer"];</syntaxhighlight> |
||
{{works with|PHP|5.3}} |
{{works with|PHP|5.3}} |
||
Since php 5.3, one can easily read and write any protected and private member in a object via reflection. |
Since php 5.3, one can easily read and write any protected and private member in a object via reflection. |
||
< |
<syntaxhighlight lang="php"><?php |
||
class fragile { |
class fragile { |
||
private $foo = 'bar'; |
private $foo = 'bar'; |
||
Line 1,134: | Line 1,270: | ||
$rp->setValue($fragile, 'haxxorz!'); |
$rp->setValue($fragile, 'haxxorz!'); |
||
var_dump($rp->getValue($fragile)); |
var_dump($rp->getValue($fragile)); |
||
var_dump($fragile);</ |
var_dump($fragile);</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 1,144: | Line 1,280: | ||
} |
} |
||
</pre> |
</pre> |
||
=={{header|PicoLisp}}== |
=={{header|PicoLisp}}== |
||
PicoLisp uses [http://software-lab.de/doc/ref.html#transient "transient symbols"] for variables, functions, methods etc. inaccessible from other parts of the program. Lexically, a transient symbol is enclosed by double quotes. |
PicoLisp uses [http://software-lab.de/doc/ref.html#transient "transient symbols"] for variables, functions, methods etc. inaccessible from other parts of the program. Lexically, a transient symbol is enclosed by double quotes. |
||
The only way to access a transient symbol outside its namespace is to search for its name in other (public) structures. This is done by the '[http://software-lab.de/doc/refL.html#loc loc]' function. |
The only way to access a transient symbol outside its namespace is to search for its name in other (public) structures. This is done by the '[http://software-lab.de/doc/refL.html#loc loc]' function. |
||
< |
<syntaxhighlight lang="picolisp">(class +Example) |
||
# "_name" |
# "_name" |
||
Line 1,159: | Line 1,294: | ||
(====) # Close transient scope |
(====) # Close transient scope |
||
(setq Foo (new '(+Example) "Eric"))</ |
(setq Foo (new '(+Example) "Eric"))</syntaxhighlight> |
||
Test: |
Test: |
||
< |
<syntaxhighlight lang="picolisp">: (string> Foo) # Access via method call |
||
-> "Hello, I am Eric" |
-> "Hello, I am Eric" |
||
Line 1,180: | Line 1,315: | ||
: (get Foo (loc "_name" +Example)) |
: (get Foo (loc "_name" +Example)) |
||
-> "Edith"</ |
-> "Edith"</syntaxhighlight> |
||
=={{header|Python}}== |
=={{header|Python}}== |
||
Python isn't heavily into private class names. Although private class names can be defined by using a double underscore at the start of the name, such names are accessible as they are mangled into the original name preceded by the name of its class as shown in this example: |
Python isn't heavily into private class names. Although private class names can be defined by using a double underscore at the start of the name, such names are accessible as they are mangled into the original name preceded by the name of its class as shown in this example: |
||
< |
<syntaxhighlight lang="python">>>> class MyClassName: |
||
__private = 123 |
__private = 123 |
||
non_private = __private * 2 |
non_private = __private * 2 |
||
Line 1,199: | Line 1,333: | ||
>>> mine._MyClassName__private |
>>> mine._MyClassName__private |
||
123 |
123 |
||
>>> </ |
>>> </syntaxhighlight> |
||
=={{header|Raku}}== |
=={{header|Raku}}== |
||
(formerly Perl 6) |
(formerly Perl 6) |
||
{{works with|Rakudo|2015.12}} |
{{works with|Rakudo|2015.12}} |
||
We may call into the MOP (Meta-Object Protocol) via the <tt>.^</tt> operator, and the MOP knows all about the object, including any supposedly private bits. We ask for its attributes, find the correct one, and get its value. |
We may call into the MOP (Meta-Object Protocol) via the <tt>.^</tt> operator, and the MOP knows all about the object, including any supposedly private bits. We ask for its attributes, find the correct one, and get its value. |
||
<lang |
<syntaxhighlight lang="raku" line>class Foo { |
||
has $!shyguy = 42; |
has $!shyguy = 42; |
||
} |
} |
||
my Foo $foo .= new; |
my Foo $foo .= new; |
||
say $foo.^attributes.first('$!shyguy').get_value($foo);</ |
say $foo.^attributes.first('$!shyguy').get_value($foo);</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>42</pre> |
<pre>42</pre> |
||
=={{header|Ruby}}== |
=={{header|Ruby}}== |
||
Ruby lets you redefine great parts of the object model at runtime and provides several methods to do so conveniently. For a list of all available methods look up the documentation of <code>Object</code> and <code>Module</code> or call informative methods at runtime (<code>puts Object.methods</code>). |
Ruby lets you redefine great parts of the object model at runtime and provides several methods to do so conveniently. For a list of all available methods look up the documentation of <code>Object</code> and <code>Module</code> or call informative methods at runtime (<code>puts Object.methods</code>). |
||
< |
<syntaxhighlight lang="ruby"> |
||
class Example |
class Example |
||
def initialize |
def initialize |
||
Line 1,234: | Line 1,366: | ||
p example.instance_variable_set :@private_data, 42 # => 42 |
p example.instance_variable_set :@private_data, 42 # => 42 |
||
p example.instance_variable_get :@private_data # => 42 |
p example.instance_variable_get :@private_data # => 42 |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Scala}}== |
=={{header|Scala}}== |
||
{{libheader|Scala}}< |
{{libheader|Scala}}<syntaxhighlight lang="scala">class Example(private var name: String) { |
||
override def toString = s"Hello, I am $name" |
override def toString = s"Hello, I am $name" |
||
} |
} |
||
Line 1,249: | Line 1,380: | ||
field.set(foo, "Edith") |
field.set(foo, "Edith") |
||
println(foo) |
println(foo) |
||
}</ |
}</syntaxhighlight> |
||
=={{header|Sidef}}== |
=={{header|Sidef}}== |
||
Sidef's object model does not enforce privacy, but it allows storing private attributes inside the container of an object, which is an hash: |
Sidef's object model does not enforce privacy, but it allows storing private attributes inside the container of an object, which is an hash: |
||
< |
<syntaxhighlight lang="ruby">class Example { |
||
has public = "foo" |
has public = "foo" |
||
method init { |
method init { |
||
Line 1,267: | Line 1,397: | ||
# Access private attributes |
# Access private attributes |
||
say obj{:private}; #=> "secret"</ |
say obj{:private}; #=> "secret"</syntaxhighlight> |
||
=={{header|Swift}}== |
=={{header|Swift}}== |
||
Swift reflection provides a Collection of label-value pairs for struct properties |
Swift reflection provides a Collection of label-value pairs for struct properties |
||
< |
<syntaxhighlight lang="swift">struct Example { |
||
var notSoSecret = "Hello!" |
var notSoSecret = "Hello!" |
||
private var secret = 42 |
private var secret = 42 |
||
Line 1,282: | Line 1,411: | ||
print("Value of the secret is \(secret)") |
print("Value of the secret is \(secret)") |
||
} |
} |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
<pre>Value of the secret is 42</pre> |
<pre>Value of the secret is 42</pre> |
||
=={{header|Tcl}}== |
=={{header|Tcl}}== |
||
Tcl's object properties are just variables in the a per-instance namespace; all that's required to get hold of them is to discover the name of the namespace concerned: |
Tcl's object properties are just variables in the a per-instance namespace; all that's required to get hold of them is to discover the name of the namespace concerned: |
||
< |
<syntaxhighlight lang="tcl">package require Tcl 8.6 |
||
oo::class create Example { |
oo::class create Example { |
||
Line 1,298: | Line 1,426: | ||
$e print |
$e print |
||
set [info object namespace $e]::name "Edith" |
set [info object namespace $e]::name "Edith" |
||
$e print</ |
$e print</syntaxhighlight>{{out}} |
||
Hello, I am Eric |
Hello, I am Eric |
||
Hello, I am Edith |
Hello, I am Edith |
||
=={{header|Visual Basic .NET}}== |
=={{header|Visual Basic .NET}}== |
||
{{trans|C#}} |
{{trans|C#}} |
||
Line 1,308: | Line 1,435: | ||
Like the other .NET languages, VB can use Reflection ([https://docs.microsoft.com/en-us/dotnet/framework/reflection-and-codedom/reflection Microsoft docs]). |
Like the other .NET languages, VB can use Reflection ([https://docs.microsoft.com/en-us/dotnet/framework/reflection-and-codedom/reflection Microsoft docs]). |
||
< |
<syntaxhighlight lang="vbnet">Imports System.Reflection |
||
' MyClass is a VB keyword. |
' MyClass is a VB keyword. |
||
Line 1,322: | Line 1,449: | ||
Console.WriteLine(answer) |
Console.WriteLine(answer) |
||
End Sub |
End Sub |
||
End Class</ |
End Class</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>42</pre> |
<pre>42</pre> |
||
=={{header|Wren}}== |
=={{header|Wren}}== |
||
In Wren all instance and static fields of a class are private and are prefixed by an underscore and a double underscore respectively. There is no way to break the privacy of such fields that I'm aware of (Wren doesn't have reflection). If one wants to provide public access to fields then this is done via getter and/or setter methods. |
In Wren all instance and static fields of a class are private and are prefixed by an underscore and a double underscore respectively. There is no way to break the privacy of such fields that I'm aware of (Wren doesn't have reflection). If one wants to provide public access to fields then this is done via getter and/or setter methods. |
||
However, there is no such thing as a private method. Although conventionally methods which are not intended to be called from outside the class are suffixed with an underscore, this doesn't prevent anyone from accessing them as the following example shows. |
However, there is no such thing as a private method. Although conventionally methods which are not intended to be called from outside the class are suffixed with an underscore, this doesn't prevent anyone from accessing them as the following example shows. |
||
< |
<syntaxhighlight lang="wren">class Safe { |
||
construct new() { _safe = 42 } // the field _safe is private |
construct new() { _safe = 42 } // the field _safe is private |
||
safe { _safe } // provides public access to field |
safe { _safe } // provides public access to field |
||
Line 1,340: | Line 1,466: | ||
var s = Safe.new() |
var s = Safe.new() |
||
var a = [s.safe, s.doubleSafe, s.notSoSafe_] |
var a = [s.safe, s.doubleSafe, s.notSoSafe_] |
||
for (e in a) System.print(e)</ |
for (e in a) System.print(e)</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 1,351: | Line 1,477: | ||
=={{header|zkl}}== |
=={{header|zkl}}== |
||
In zkl, privacy is more convention than enforced (unlike const or protected). |
In zkl, privacy is more convention than enforced (unlike const or protected). |
||
< |
<syntaxhighlight lang="zkl">class C{var [private] v; fcn [private] f{123} class [private] D {}} |
||
C.v; C.f; C.D; // all generate NotFoundError exceptions |
C.v; C.f; C.D; // all generate NotFoundError exceptions |
||
However: |
However: |
||
Line 1,357: | Line 1,483: | ||
C.fcns[1]() //-->123 |
C.fcns[1]() //-->123 |
||
C.classes //-->L(Class(D)) |
C.classes //-->L(Class(D)) |
||
C.vars //-->L(L("",Void)) (name,value) pairs</ |
C.vars //-->L(L("",Void)) (name,value) pairs</syntaxhighlight> |
||
In the case of private vars, the name isn't saved. |
In the case of private vars, the name isn't saved. |
||
{{omit from|6502 Assembly}} |
|||
{{omit from|8086 Assembly}} |
|||
{{omit from|68000 Assembly}} |
|||
{{omit from|ARM Assembly}} |
|||
{{omit from|AWK}} |
|||
{{omit from|BASIC}} |
|||
{{omit from|BBC BASIC}} |
|||
{{omit from|C}} |
|||
{{omit from|Déjà Vu}} |
|||
{{omit from|GUISS}} |
|||
{{omit from|Haskell}} |
|||
{{omit from|Icon}} |
|||
{{omit from|Locomotive Basic}} |
|||
{{omit from|Lotus 123 Macro Scripting}} |
|||
{{omit from|Mathematica}} |
|||
{{omit from|Rust}} |
|||
{{omit from|R}} |
|||
{{omit from|SmileBASIC}} |
|||
{{omit from|Standard ML|not OO}} |
{{omit from|Standard ML|not OO}} |
||
{{omit from|x86 Assembly}} |
|||
{{omit from|Z80 Assembly}} |
|||
{{omit from|Zig}} |
|||
{{omit from|ZX Spectrum Basic}} |
|||
{{omit from|Insitux}} |
Latest revision as of 17:58, 12 November 2023
You are encouraged to solve this task according to the task description, using any language you may know.
Show how to access private or protected members of a class in an object-oriented language from outside an instance of the class, without calling non-private or non-protected members of the class as a proxy. The intent is to show how a debugger, serializer, or other meta-programming tool might access information that is barred by normal access methods to the object but can nevertheless be accessed from within the language by some provided escape hatch or reflection mechanism. The intent is specifically not to demonstrate heroic measures such as peeking and poking raw memory.
Note that cheating on your type system is almost universally regarded as unidiomatic at best, and poor programming practice at worst. Nonetheless, if your language intentionally maintains a double-standard for OO privacy, here's where you can show it off.
ABAP
Similar to C++, ABAP allows the declaration of friends which can be both classes and interfaces. All subclasses of friend classes are automatically friends of the source class. For example if classA (source) has classB as a friend and classC is a subclass of classB then classC is a friend of classA. Similarly all implementing classes of friend interfaces are friends of the source class. Also all interfaces which contain the befriended interface as a component are friends of the source class.
class friendly_class definition deferred.
class my_class definition friends friendly_class .
public section.
methods constructor.
private section.
data secret type char30.
endclass.
class my_class implementation .
method constructor.
secret = 'a password'. " Instantiate secret.
endmethod.
endclass.
class friendly_class definition create public .
public section.
methods return_secret
returning value(r_secret) type char30.
endclass.
class friendly_class implementation.
method return_secret.
data lr_my_class type ref to my_class.
create object lr_my_class. " Instantiate my_class
write lr_my_class->secret. " Here's the privacy violation.
endmethod.
endclass.
Ada
One of the great criticisms of Pascal was "there is no escape". The reason was that sometimes you have to convert the incompatible. We start with a package, which defines the data type which holds the secret.
package OO_Privacy is
type Confidential_Stuff is tagged private;
subtype Password_Type is String(1 .. 8);
private
type Confidential_Stuff is tagged record
Password: Password_Type := "default!"; -- the "secret"
end record;
end OO_Privacy;
When we later define an object C of type Confidential_Stuff, we can't read read the password stored in C -- except by breaking / bypassing OO privacy rules.
Using Unchecked_Conversion
One way to read the password is by using the generic function Unchecked_Conversion:
with OO_Privacy, Ada.Unchecked_Conversion, Ada.Text_IO;
procedure OO_Break_Privacy is
type Hacker_Stuff is tagged record
Password: OO_Privacy.Password_Type := "?unknown";
end record;
function Hack is new Ada.Unchecked_Conversion
(Source => OO_Privacy.Confidential_Stuff, Target => Hacker_Stuff);
C: OO_Privacy.Confidential_Stuff; -- which password is hidden inside C?
begin
Ada.Text_IO.Put_Line("The secret password is """ & Hack(C).Password & """");
end OO_Break_Privacy;
The output shows that C holds, surprise, surprise, the default password:
The secret password is "default!"
Child Packages
Another way to bypass privacy is using a child package. Ada child packages have access to their parents' private data structures (somewhat similar to "friends" in C++"):
package OO_Privacy.Friend is -- child package of OO.Privacy
function Get_Password(Secret: Confidential_Stuff) return String;
end OO_Privacy.Friend;
package body OO_Privacy.Friend is -- implementation of the child package
function Get_Password(Secret: Confidential_Stuff) return String is
(Secret.Password);
end OO_Privacy.Friend;
Now here is the program that uses the child package, to read the secret:
with OO_Privacy.Friend, Ada.Text_IO;
procedure Bypass_OO_Privacy is
C: OO_Privacy.Confidential_Stuff; -- which password is hidden inside C?
begin
Ada.Text_IO.Put_Line("Password: """ &
OO_Privacy.Friend.Get_Password(C) &
"""");
end Bypass_OO_Privacy;
Once again, we have been too lazy to overwrite the default password:
Password: "default!"
In fact, the password has to be the default one, because we cannot change the password. For that purpose, we would have to write a setter procedure, and either include it in the package OO_Privacy, or in a child package of OO_Privacy. (Or we could use Unchecked_Conversion to overwrite the default password -- but that is bad style.)
C#
using System;
using System.Reflection;
public class MyClass
{
private int answer = 42;
}
public class Program
{
public static void Main()
{
var myInstance = new MyClass();
var fieldInfo = typeof(MyClass).GetField("answer", BindingFlags.NonPublic | BindingFlags.Instance);
var answer = fieldInfo.GetValue(myInstance);
Console.WriteLine(answer);
}
}
- Output:
42
C++
C++ has the 'friend' keyword to indicate that one class should have access to the private data of another. Here's a simple use case. (Please note that this code is not thread-safe.)
#include <iostream>
class CWidget; // Forward-declare that we have a class named CWidget.
class CFactory
{
friend class CWidget;
private:
unsigned int m_uiCount;
public:
CFactory();
~CFactory();
CWidget* GetWidget();
};
class CWidget
{
private:
CFactory& m_parent;
private:
CWidget(); // Disallow the default constructor.
CWidget(const CWidget&); // Disallow the copy constructor
CWidget& operator=(const CWidget&); // Disallow the assignment operator.
public:
CWidget(CFactory& parent);
~CWidget();
};
// CFactory constructors and destructors. Very simple things.
CFactory::CFactory() : m_uiCount(0) {}
CFactory::~CFactory() {}
// CFactory method which creates CWidgets.
CWidget* CFactory::GetWidget()
{
// Create a new CWidget, tell it we're its parent.
return new CWidget(*this);
}
// CWidget constructor
CWidget::CWidget(CFactory& parent) : m_parent(parent)
{
++m_parent.m_uiCount;
std::cout << "Widget spawning. There are now " << m_parent.m_uiCount << " Widgets instanciated." << std::endl;
}
CWidget::~CWidget()
{
--m_parent.m_uiCount;
std::cout << "Widget dieing. There are now " << m_parent.m_uiCount << " Widgets instanciated." << std::endl;
}
int main()
{
CFactory factory;
CWidget* pWidget1 = factory.GetWidget();
CWidget* pWidget2 = factory.GetWidget();
delete pWidget1;
CWidget* pWidget3 = factory.GetWidget();
delete pWidget3;
delete pWidget2;
}
- Output:
Widget spawning. There are now 1 Widgets instanciated.
Widget spawning. There are now 2 Widgets instanciated.
Widget dieing. There are now 1 Widgets instanciated.
Widget spawning. There are now 2 Widgets instanciated.
Widget dieing. There are now 1 Widgets instanciated.
Widget dieing. There are now 0 Widgets instanciated.
Without the "friend" mechanism, it's still possible to meaningfully modify any member in another class, as long as you know that member's address in memory, and its type. Here's the same program as above, but using a pointer to m_uicount, rather a reference to the factory:
#include <iostream>
class CWidget; // Forward-declare that we have a class named CWidget.
class CFactory
{
private:
unsigned int m_uiCount;
public:
CFactory();
~CFactory();
CWidget* GetWidget();
};
class CWidget
{
private:
unsigned int* m_pCounter;
private:
CWidget(); // Disallow the default constructor.
CWidget(const CWidget&); // Disallow the copy constructor
CWidget& operator=(const CWidget&); // Disallow the assignment operator.
public:
CWidget(unsigned int* pCounter);
~CWidget();
};
// CFactory constructors and destructors. Very simple things.
CFactory::CFactory() : m_uiCount(0) {}
CFactory::~CFactory() {}
// CFactory method which creates CWidgets.
CWidget* CFactory::GetWidget()
{
// Create a new CWidget, tell it we're its parent.
return new CWidget(&m_uiCount);
}
// CWidget constructor
CWidget::CWidget(unsigned int* pCounter) : m_pCounter(pCounter)
{
++*m_pCounter;
std::cout << "Widget spawning. There are now " << *m_pCounter<< " Widgets instanciated." << std::endl;
}
CWidget::~CWidget()
{
--*m_pCounter;
std::cout << "Widget dieing. There are now " << *m_pCounter<< " Widgets instanciated." << std::endl;
}
int main()
{
CFactory factory;
CWidget* pWidget1 = factory.GetWidget();
CWidget* pWidget2 = factory.GetWidget();
delete pWidget1;
CWidget* pWidget3 = factory.GetWidget();
delete pWidget3;
delete pWidget2;
}
Clojure
You can use the var-quote macro to get values from private variables. Here's an example of a variable 'priv' marked private in namespace 'a':
(ns a)
(def ^:private priv :secret)
; From REPL, in another namespace 'user':
user=> @a/priv ; fails with: IllegalStateException: var: a/priv is not public
user=> @#'a/priv ; succeeds
:secret
Clojure can also access Java private variables with the same strategy that Java uses. As a convenience, use the get-field function from clojure.contrib.reflect. Here's an example of grabbing the private field "serialVersionUID" from java.lang.Double:
user=> (get-field Double "serialVersionUID" (Double/valueOf 1.0))
-9172774392245257468
Common Lisp
Common Lisp doesn't have concepts like class scopes, name lookup rules, or access. Essentially, the way things are referenced in the source code (the static view of the program) is not involved in the class hierarchy. For instance, when a class is derived from another one, it is purely an object-oriented inheritance. There is no parallel symbol-table inheritance going on whereby one namespace becomes a tributary of another (the identifier scope of a derived class inheriting symbols from, or a visibility window into the base class).
The primary concept of naming privacy in Lisp is located in the package system.
An external symbol S in package P can be accessed using P:S. If S is internal then P:S results in error at read time.
This is completely independent of context and orthogonal to the use of symbols to denote class slots (instance variables), methods, functions, class names themselves, global variables, et cetera.
Even if the private symbol appears in a literal piece of data like a quoted list, it is an error to refer to it: (1 2 3 P:S)
.
The internal symbol S in package P can be accessed using P::S
.
This is easy to do because programmers are assumed to be responsible grownups who can be trusted to know what they are doing.
Also, note that this privacy is a property of the relationship between a symbol and a package.
A symbol can be present in more than one package, such that it can be internal in some of them, and external in others.
(defpackage :funky
;; only these symbols are public
(:export :widget :get-wobbliness)
;; for convenience, bring common lisp symbols into funky
(:use :cl))
;; switch reader to funky package: all symbols that are
;; not from the CL package are interned in FUNKY.
(in-package :funky)
(defclass widget ()
;; :initarg -> slot "wobbliness" is initialized using :wobbliness keyword
;; :initform -> if initarg is missing, slot defaults to 42
;; :reader -> a "getter" method called get-wobbliness is generated
((wobbliness :initarg :wobbliness :initform 42 :reader get-wobbliness)))
;; simulate being in another source file with its own package:
;; cool package gets external symbols from funky, and cl:
(defpackage :cool
(:use :funky :cl))
(in-package :cool)
;; we can use the symbol funky:widget without any package prefix:
(defvar *w* (make-instance 'widget :wobbliness 36))
;; ditto with funky:get-wobbliness
(format t "wobbliness: ~a~%" (get-wobbliness *w*))
;; direct access to the slot requires fully qualified private symbol
;; and double colon:
(format t "wobbliness: ~a~%" (slot-value *w* 'funky::wobbliness))
;; if we use unqualified wobbliness, it's a different symbol:
;; it is cool::wobbliness interned in our local package.
;; we do not have funky:wobbliness because it's not exported by funky.
(unless (ignore-errors
(format t "wobbliness: ~a~%" (slot-value *w* 'wobbliness)))
(write-line "didn't work"))
;; single colon results in error at read time! The expression is not
;; even read and evaluated. The symbol is internal and so cannot be used.
(format t "wobbliness: ~a~%" (slot-value *w* 'funky:wobbliness))
- Output:
using CLISP
wobbliness: 36 wobbliness: 36 didn't work *** - READ from #<INPUT BUFFERED FILE-STREAM CHARACTER #P"funky.lisp" @44>: #<PACKAGE FUNKY> has no external symbol with name "WOBBLINESS"
D
Private members can be accessed by other code in the same module. You can access private members of structs/classes imported from another module using compile time reflection.
breakingprivacy.d:
module breakingprivacy;
struct Foo
{
int[] arr;
private:
int x;
string str;
float f;
}
app.d:
import std.stdio;
import breakingprivacy;
void main()
{
auto foo = Foo([1,2,3], 42, "Hello World!", 3.14);
writeln(foo);
// __traits(getMember, obj, name) allows you to access any field of obj given its name
// Reading a private field
writeln("foo.x = ", __traits(getMember, foo, "x"));
// Writing to a private field
__traits(getMember, foo, "str") = "Not so private anymore!";
writeln("Modified foo: ", foo);
}
- Output:
Foo([1, 2, 3], 42, "Hello World!", 3.14)
foo.x = 42
Modified foo: Foo([1, 2, 3], 42, "Not so private anymore!", 3.14)
E
In its goal of supporting programs including mutually suspicious robust components and potentially executing untrusted code, E specifically does not provide any means within the language to break the encapsulation of an object. The official answer to how you access private state is: evaluate the code with a special evaluator which permits such access to the objects the code creates, or, entirely equivalently, transform the code so that each object definition has hooks for private access.
Ecstasy
In Ecstasy, using the keywords public , protected , and private to mark classes and class members is solely for the benefit of the developer, and not in any way related to security. These keywords help the developer to classify information among three categories: Things that are useful to everyone; things that are useful to further compositions (such as sub-classes and mixins); and things that, were they exposed, would likely to create an ugly mess. Information hiding is about organization, and not about security.
An Ecstasy reference contains both its type (the type of the reference itself, as opposed to the type of the referred-to object, a.k.a. the referent), and the means -- a "pointer" or a "value" -- to refer to the referent. By default, the type of a reference is of the public type of the referent, but it is possible to reveal the referent as any other legal type -- where legal simply means that strong type safety is enforced. This is not a type cast; it is a request to the runtime to provide a different reference to the same underlying object.
Ecstasy security is accomplished by the use of software containers. Code running in a container is always allowed reveal any legal type on any object created within that container, including any object created within sub-containers. However, the runtime will reject any reveal request on any object that was not created within that container.
module BreakOO {
/**
* This is a class with public, protected, and private properties.
*/
class Exposed {
public String pub = "public";
protected String pro = "protected";
private String pri = "private";
@Override
String toString() {
return $"pub={pub.quoted()}, pro={pro.quoted()}, pri={pri.quoted()}";
}
}
void run() {
@Inject Console console;
Exposed expo = new Exposed();
console.print($"before: {expo}");
// you can only access public members from the default reference
expo.pub = $"this was {expo.pub}";
// expo.pro = $"this was {expo.pro}"; <- compiler error
// expo.pri = $"this was {expo.pri}"; <- compiler error
// but you can ask for the protected reference ...
assert (protected Exposed) expoPro := &expo.revealAs((protected Exposed));
expoPro.pro = $"this was {expoPro.pro}";
// expoPro.pri = $"this was {expoPro.pri}"; <- compiler error
// and you can ask for the private reference ...
assert (private Exposed) expoPri := &expo.revealAs((private Exposed));
expoPri.pri = $"this was {expoPri.pri}";
// or you can ask for the underlying struct, which is a passive
// object that contains only the field storage
assert (struct Exposed) expoStr := &expo.revealAs((struct Exposed));
expoStr.pub = $"{expoStr.pub}!!!";
expoStr.pro = $"{expoStr.pro}!!!";
expoStr.pri = $"{expoStr.pri}!!!";
console.print($"after: {expo}");
}
}
- Output:
before: pub="public", pro="protected", pri="private" after: pub="this was public!!!", pro="this was protected!!!", pri="this was private!!!"
F#
open System
open System.Reflection
type MyClass() =
let answer = 42
member this.GetAnswer
with get() = answer
[<EntryPoint>]
let main argv =
let myInstance = MyClass()
let fieldInfo = myInstance.GetType().GetField("answer", BindingFlags.NonPublic ||| BindingFlags.Instance)
let answer = fieldInfo.GetValue(myInstance)
printfn "%s = %A" (answer.GetType().ToString()) answer
0
- Output:
System.Int32 = 42
Factor
From the documentation for private words: "Privacy is not enforced by the system; private words can be called from other vocabularies, and from the listener. However, this should be avoided where possible."
This example uses the private word sequence/tester from the vocabulary sets.private. It tries to count the elements in an intersection of two sets.
( scratchpad ) USING: sets sets.private ;
( scratchpad ) { 1 2 3 } { 1 2 4 } sequence/tester count .
2
There is better way to do the same, without any private words.
( scratchpad ) USE: sets
( scratchpad ) { 1 2 3 } { 1 2 4 } intersect length .
2
Forth
Works with any ANS Forth
Needs the FMS-SI (single inheritance) library code located here: http://soton.mpeforth.com/flag/fms/index.html
include FMS-SI.f
99 value x \ create a global variable named x
:class foo
ivar x \ this x is private to the class foo
:m init: 10 x ! ;m \ constructor
:m print x ? ;m
;class
foo f1 \ instantiate a foo object
f1 print \ 10 access the private x with the print message
x . \ 99 x is a globally scoped name
50 .. f1.x ! \ use the dot parser to access the private x without a message
f1 print \ 50
FreeBASIC
FreeBASIC generally does a good job of maintaining OO privacy as it doesn't support reflection and even its OffsetOf keyword cannot obtain the offset within a user defined type of a private or protected field. You therefore have to guess the offset of a non-public field in order to be able to access it using a raw pointer though this is not generally a difficult task.
However, as usual, macros come to the rescue and one can easily access non-public members by the simple expedient (or, if you prefer, 'dirty hack') of redefining the Private and Protected keywords to mean Public:
'FB 1.05.0 Win64
#Undef Private
#Undef Protected
#Define Private Public
#Define Protected Public
Type MyType
Public :
x As Integer = 1
Protected :
y As Integer = 2
Private :
z As Integer = 3
End Type
Dim mt As MyType
Print mt.x, mt.y, mt.z
Print
Print "Press any key to quit"
Sleep
- Output:
1 2 3
Go
Go has a reflect
and unsafe
package that together can do this.
Of course, as mentioned in the task description, this is a bad idea.
A relevant Go Blog article is The Laws of Reflection.
package main
import (
"bufio"
"errors"
"fmt"
"os"
"reflect"
"unsafe"
)
type foobar struct {
Exported int // In Go identifiers that are capitalized are exported,
unexported int // while lowercase identifiers are not.
}
func main() {
obj := foobar{12, 42}
fmt.Println("obj:", obj)
examineAndModify(&obj)
fmt.Println("obj:", obj)
anotherExample()
}
// For simplicity this skips several checks. It assumes the thing in the
// interface is a pointer without checking (v.Kind()==reflect.Ptr),
// it then assumes it is a structure type with two int fields
// (v.Kind()==reflect.Struct, f.Type()==reflect.TypeOf(int(0))).
func examineAndModify(any interface{}) {
v := reflect.ValueOf(any) // get a reflect.Value
v = v.Elem() // dereference the pointer
fmt.Println(" v:", v, "=", v.Interface())
t := v.Type()
// Loop through the struct fields
fmt.Printf(" %3s %-10s %-4s %s\n", "Idx", "Name", "Type", "CanSet")
for i := 0; i < v.NumField(); i++ {
f := v.Field(i) // reflect.Value of the field
fmt.Printf(" %2d: %-10s %-4s %t\n", i,
t.Field(i).Name, f.Type(), f.CanSet())
}
// "Exported", field 0, has CanSet==true so we can do:
v.Field(0).SetInt(16)
// "unexported", field 1, has CanSet==false so the following
// would fail at run-time with:
// panic: reflect: reflect.Value.SetInt using value obtained using unexported field
//v.Field(1).SetInt(43)
// However, we can bypass this restriction with the unsafe
// package once we know what type it is (so we can use the
// correct pointer type, here *int):
vp := v.Field(1).Addr() // Take the fields's address
up := unsafe.Pointer(vp.Pointer()) // … get an int value of the address and convert it "unsafely"
p := (*int)(up) // … and end up with what we want/need
fmt.Printf(" vp has type %-14T = %v\n", vp, vp)
fmt.Printf(" up has type %-14T = %#0x\n", up, up)
fmt.Printf(" p has type %-14T = %v pointing at %v\n", p, p, *p)
*p = 43 // effectively obj.unexported = 43
// or an incr all on one ulgy line:
*(*int)(unsafe.Pointer(v.Field(1).Addr().Pointer()))++
// Note that as-per the package "unsafe" documentation,
// the return value from vp.Pointer *must* be converted to
// unsafe.Pointer in the same expression; the result is fragile.
//
// I.e. it is invalid to do:
// thisIsFragile := vp.Pointer()
// up := unsafe.Pointer(thisIsFragile)
}
// This time we'll use an external package to demonstrate that it's not
// restricted to things defined locally. We'll mess with bufio.Reader's
// interal workings by happening to know they have a non-exported
// "err error" field. Of course future versions of Go may not have this
// field or use it in the same way :).
func anotherExample() {
r := bufio.NewReader(os.Stdin)
// Do the dirty stuff in one ugly and unsafe statement:
errp := (*error)(unsafe.Pointer(
reflect.ValueOf(r).Elem().FieldByName("err").Addr().Pointer()))
*errp = errors.New("unsafely injected error value into bufio inner workings")
_, err := r.ReadByte()
fmt.Println("bufio.ReadByte returned error:", err)
}
- Output:
obj: {12 42} v: <main.foobar Value> = {12 42} Idx Name Type CanSet 0: Exported int true 1: unexported int false vp has type reflect.Value = <*int Value> up has type unsafe.Pointer = 0xc208000208 p has type *int = 0xc208000208 pointing at 42 obj: {16 44} bufio.ReadByte returned error: unsafely injected error value into bufio inner workings
Icon and Unicon
Unicon implements object environments with records and supporting procedures for creation, initialization, and methods. The variables in the class environment can be accessed like any other record field. Additionally, with the fieldnames procedure you can obtain the names of the class variables.
In addition to debuggers and diagnostic tools, these techniques could be used in 'monkey patching' extensions (see Add_a_variable_to_a_class_instance_at_runtime).
Note: Unicon can be translated via a command line switch into icon which allows for classes to be shared with Icon code (assuming no other incompatibilities exist).
link printf
procedure main()
(x := foo(1,2,3)).print() # create and show a foo
printf("Fieldnames of foo x : ") # show fieldnames
every printf(" %i",fieldnames(x)) # __s (self), __m (methods), vars
printf("\n")
printf("var 1 of foo x = %i\n", x.var1) # read var1 from outside x
x.var1 := -1 # change var1 from outside x
x.print() # show we changed it
end
class foo(var1,var2,var3) # class with no set/read methods
method print()
printf("foo var1=%i, var2=%i, var3=%i\n",var1,var2,var3)
end
end
printf.icn provides formatting
Output:
foo var1=1, var2=2, var3=3 Fieldnames of foo x : "__s" "__m" "var1" "var2" "var3" var 1 of foo x = 1 foo var1=-1, var2=2, var3=3
J
Current implementations of J do not enforce OO privacy, instead favoring design techniques (such as functional programming) which eliminate private information in persistent contexts.
It's possible to use OS features (such as other processes, and servers) to hide information. But that, by definition, is outside the scope of the language.
J does support a "Lock Script" mechanism - to transform a J script so that it's unreadable. However, anyone with access to a machine running the code and ordinary developer tools or who understands the "locking" technique could unlock it.
Java
In order the access a class member of another class which is marked as private
, you'll need to use reflection.
Java offers a collection of reflection-related utilities within the java.lang.reflect
package.
In this example I'll use a class with two fields, stringA
and stringB
.
class Example {
String stringA = "rosetta";
private String stringB = "code";
}
From another class, I'll instantiate Example
, and use a Field
object to return a specified, declared field.
To do this you call the getDeclaredField
on your Class
object, supplying the name of the field.
Example example = new Example();
Field field = example.getClass().getDeclaredField("stringB");
To allow access to stringB
we'll need to use the Field.setAccessible
method, and signify true.
This is essentially what the task is looking for, the ability to override the access-modifier.
field.setAccessible(true);
Now, we can access the data from the field by using the Field.get
method, specifying the instance as the parameter.
String stringB = (String) field.get(example);
So, all together our method would contain the following lines.
Example example = new Example();
Field field = example.getClass().getDeclaredField("stringB");
field.setAccessible(true);
String stringA = example.stringA;
String stringB = (String) field.get(example);
System.out.println(stringA + " " + stringB);
With an output of the following.
rosetta code
If we hadn't used the Field.setAccessible
method, we would get an IllegalAccessException
.
cannot access a member of class Example with modifiers "private"
Additionally, you can do this with methods via the Method
object.
Consider the following class.
class Example {
String stringA = "rosetta";
private String stringB() {
return "code";
}
}
The approach is the same, except we are using getDeclaredMethod
, and instead of get
we are using invoke
.
Example example = new Example();
Method method = example.getClass().getDeclaredMethod("stringB");
method.setAccessible(true);
String stringA = example.stringA;
String stringB = (String) method.invoke(example);
System.out.println(stringA + " " + stringB);
rosetta code
Julia
Julia's object model is one of structs which contain data and methods which are just functions using those structs, with multiple dispatch, rather than object methods, used to distinguish similarly named calls for different object types. Julia does not therefore enforce any private fields in its structures, since, except for constructors, it does not distinguish object methods from other functions. If private fields or methods are actually needed they can be kept from view by placing them inside a module which cannot be directly accessed by user code, such as in a module within a module.
Kotlin
For tasks such as this, reflection is your friend:
import kotlin.reflect.full.declaredMemberProperties
import kotlin.reflect.jvm.isAccessible
class ToBeBroken {
@Suppress("unused")
private val secret: Int = 42
}
fun main(args: Array<String>) {
val tbb = ToBeBroken()
val props = ToBeBroken::class.declaredMemberProperties
for (prop in props) {
prop.isAccessible = true // make private properties accessible
println("${prop.name} -> ${prop.get(tbb)}")
}
}
- Output:
secret -> 42
Logtalk
Logtalk provides a context switching call control construct that allows a call to be executed as from within an object. It's mainly used for debugging and for writing unit tests. This control construct can be disabled on a global or per object basis to prevent it of being used to break encapsulation.
In the following example, a prototype is used for simplicity.
:- object(foo).
% be sure that context switching calls are allowed
:- set_logtalk_flag(context_switching_calls, allow).
% declare and define a private method
:- private(bar/1).
bar(1).
bar(2).
bar(3).
:- end_object.
After compiling and loading the above object, we can use the following query to access the private method:
| ?- foo<<bar(X).
X = 1 ;
X = 2 ;
X = 3
true
Lua
Lua doesn't have a native concept of classes, and the only custom data structure available is the table (in which all fields are always public). However, it's pretty common for table/object creation functions in object-oriented code to return instances of other functions that uses local variables through lexical scoping, or their closure, which is not accessible to the outside code and could be considered a space with "private" fields. These can be accessed indirectly through the debug library.
local function Counter()
-- These two variables are "private" to this function and can normally
-- only be accessed from within this scope, including by any function
-- created inside here.
local counter = {}
local count = 0
function counter:increment()
-- 'count' is an upvalue here and can thus be accessed through the
-- debug library, as long as we have a reference to this function.
count = count + 1
end
return counter
end
-- Create a counter object and try to access the local 'count' variable.
local counter = Counter()
for i = 1, math.huge do
local name, value = debug.getupvalue(counter.increment, i)
if not name then break end -- No more upvalues.
if name == "count" then
print("Found 'count', which is "..tostring(value))
-- If the 'counter.increment' function didn't access 'count'
-- directly then we would never get here.
break
end
end
- Output:
Found 'count', which is 0
Note that there's an infinite number of other more complex ways for functions to store values in a "private" manner, and the introspection functionality of the debug library can only get you so far.
M2000 Interpreter
We want to read two private variables, and change values without using a public method (a module or a function), and without attach a temporary method (we can do that in M2000). There is a variant in READ statemend to set references from group members (for variables and arrays, and objects) to names with a reference for each. So using these names (here in the exaample K, M) we can read and write private variables.
Module CheckIt {
Group Alfa {
Private:
X=10, Y=20
Public:
Module SetXY (.X, .Y) {}
Module Print {
Print .X, .Y
}
}
Alfa.Print ' 10 20
\\ we have to KnΟw position in group
\\ so we make references from two first
Read From Alfa, K, M
Print K=10, M=20
K+=10
M+=1000
Alfa.Print ' 20 1020
}
CheckIt
Nim
File oo.nim:
type Foo* = object
a: string
b: string
c: int
proc createFoo*(a, b, c): Foo =
Foo(a: a, b: b, c: c)
By not adding a *
to Foo
's members we don't export them. When we import this module we can't use them directly:
var x = createFoo("this a", "this b", 12)
echo x.a # compile time error
The easiest way to get a debug view of any data:
echo repr(x)
Output:
[a = 0x7f6bb87a7050"this a", b = 0x7f6bb87a7078"this b", c = 12]
More fine-grained:
import typeinfo
for key, val in fields(toAny(x)):
echo "Key ", key
case val.kind
of akString:
echo " is a string with value: ", val.getString
of akInt..akInt64, akUint..akUint64:
echo " is an integer with value: ", val.getBiggestInt
else:
echo " is an unknown with value: ", val.repr
Output:
Key a is a string with value: this a Key b is a string with value: this b Key c is an integer with value: 12
Objective-C
In older versions of the compiler, you can simply access a private field from outside of the class. The compiler will give a warning, but you can ignore it and it will still compile. However, in current compiler versions it is now a hard compile error.
Key-Value Coding
One solution is to use Key-Value Coding. It treats properties and instance variables as "keys" that you can get and set using key-value coding methods.
#import <Foundation/Foundation.h>
@interface Example : NSObject {
@private
NSString *_name;
}
- (instancetype)initWithName:(NSString *)name;
@end
@implementation Example
- (NSString *)description {
return [NSString stringWithFormat:@"Hello, I am %@", _name];
}
- (instancetype)initWithName:(NSString *)name {
if ((self = [super init])) {
_name = [name copy];
}
return self;
}
@end
int main (int argc, const char * argv[]) {
@autoreleasepool{
Example *foo = [[Example alloc] initWithName:@"Eric"];
// get private field
NSLog(@"%@", [foo valueForKey:@"name"]);
// set private field
[foo setValue:@"Edith" forKey:@"name"];
NSLog(@"%@", foo);
}
return 0;
}
- Output:
Eric Hello, I am Edith
Category
Another solution is to use a category to add methods to the class (you can have categories in your code modify any class, even classes compiled by someone else, including system classes). Since the new method is in the class, it can use the class's private instance variables with no problem.
#import <Foundation/Foundation.h>
@interface Example : NSObject {
@private
NSString *_name;
}
- (instancetype)initWithName:(NSString *)name;
@end
@implementation Example
- (NSString *)description {
return [NSString stringWithFormat:@"Hello, I am %@", _name];
}
- (instancetype)initWithName:(NSString *)name {
if ((self = [super init])) {
_name = [name copy];
}
return self;
}
@end
@interface Example (HackName)
- (NSString *)getName;
- (void)setNameTo:(NSString *)newName;
@end
@implementation Example (HackName)
- (NSString *)getName {
return _name;
}
- (void)setNameTo:(NSString *)newName {
_name = [newName copy];
}
@end
int main (int argc, const char * argv[]) {
@autoreleasepool{
Example *foo = [[Example alloc] initWithName:@"Eric"];
// get private field
NSLog(@"%@", [foo getName]);
// set private field
[foo setNameTo:@"Edith"];
NSLog(@"%@", foo);
}
return 0;
}
- Output:
Eric Hello, I am Edith
Reflection
Finally, you can access the instance variable directly using runtime functions.
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
@interface Example : NSObject {
@private
NSString *_name;
}
- (instancetype)initWithName:(NSString *)name;
@end
@implementation Example
- (NSString *)description {
return [NSString stringWithFormat:@"Hello, I am %@", _name];
}
- (instancetype)initWithName:(NSString *)name {
if ((self = [super init])) {
_name = [name copy];
}
return self;
}
@end
int main (int argc, const char * argv[]) {
@autoreleasepool{
Example *foo = [[Example alloc] initWithName:@"Eric"];
// get private field
Ivar nameField = class_getInstanceVariable([foo class], "_name");
NSLog(@"%@", object_getIvar(foo, nameField));
// set private field
object_setIvar(foo, nameField, @"Edith");
NSLog(@"%@", foo);
}
return 0;
}
- Output:
Eric Hello, I am Edith
OCaml
OCaml includes a function called Obj.magic, of type 'a -> 'b.
That type alone should tell you that this function is crystallized pure evil. The following is not quite as heroic as peeking at random addresses of memory, but to repeat it does require an understanding of the physical layout of OCaml data.
In the following, point's attributes are completely private to the object. They can be revealed with print but can't be directly modified or checked at all. Obj.magic is then used to commit this lie: actually, what was a point object, can be viewed as a four-element tuple of ints. The first two values are meaningless except to OCaml internals and are discarded; the second two values are point's hidden attributes. Then, an even more sinister lie is told that allows us to mutate the point's hidden attributes. Lies of this nature can be used to mutate normally immutable data, which can directly lead to very hard to understand bugs.
The reader is advised to stop reading here.
class point x y =
object
val mutable x = x
val mutable y = y
method print = Printf.printf "(%d, %d)\n" x y
method dance =
x <- x + Random.int 3 - 1;
y <- y + Random.int 3 - 1
end
type evil_point {
blah : int;
blah2 : int;
mutable x : int;
mutable y : int;
}
let evil_reset p =
let ep = Obj.magic p in
ep.x <- 0;
ep.y <- 0
let () =
let p = new point 0 0 in
p#print;
p#dance;
p#print;
p#dance;
p#print;
let (_, _, x, y) : int * int * int * int = Obj.magic p in
Printf.printf "Broken coord: (%d, %d)\n" x y;
evil_reset p
p#print
- Output:
(0, 0) (-1, 0) (-1, -1) Broken coord: (-1, -1) (0, 0)
Oforth
In Oforth, all attributes are private.
There is no other way to access attributes values from outside but to call methods on the object.
Perl
Perl's object model does not enforce privacy. An object is just a blessed reference, and a blessed reference can be dereferenced just like an ordinary reference.
package Foo;
sub new {
my $class = shift;
my $self = { _bar => 'I am ostensibly private' };
return bless $self, $class;
}
sub get_bar {
my $self = shift;
return $self->{_bar};
}
package main;
my $foo = Foo->new();
print "$_\n" for $foo->get_bar(), $foo->{_bar};
- Output:
I am ostensibly private I am ostensibly private
Phix
Privacy operates by having a context of routine_id("classname") in force between the class..end class.
We can easily break that privacy mechanism via low-level routines with the required simulated/fake context,
and at the same time be reasonably confident that no-one is ever going to manage to achieve that by accident.
without js -- (no class under p2js) class test private string msg = "this is a test" procedure show() ?this.msg end procedure end class test t = new() t.show() --?t.msg -- illegal --t.msg = "this is broken" -- illegal include builtins\structs.e as structs constant ctx = routine_id("test") -- magic/context --constant ctx = "test" -- also works --constant ctx = test -- also works ?structs:fetch_field(t,"msg",ctx)&" (with some magic)" structs:store_field(t,"msg","this breaks privacy",ctx) t.show()
(Obviously you could inline the ctx values rather than create a separate constant.)
- Output:
"this is a test" "this is a test (with some magic)" "this breaks privacy"
PHP
While normally accessing private variables causes fatal errors, it's possible to catch output of some debugging functions and use it. Known functions which can get private variables include: var_dump()
, print_r()
, var_export()
and serialize()
. The easiest to use is var_export()
because it's both valid PHP code and doesn't recognize private and public variables.
<?php
class SimpleClass {
private $answer = "hello\"world\nforever :)";
}
$class = new SimpleClass;
ob_start();
// var_export() expects class to contain __set_state() method which would import
// data from array. But let's ignore this and remove from result the method which
// sets state and just leave data which can be used everywhere...
var_export($class);
$class_content = ob_get_clean();
$class_content = preg_replace('"^SimpleClass::__set_state\("', 'return ', $class_content);
$class_content = preg_replace('"\)$"', ';', $class_content);
$new_class = eval($class_content);
echo $new_class['answer'];
Another way commonly used to access private and protected variables in PHP is to cast the object to an array. It's probably unintentional though looking on how casted array contains null bytes (probably "private" mark). This works unless a magic method for the cast operation is implemented:
<?php
class SimpleClass {
private $answer = 42;
}
$class = new SimpleClass;
$classvars = (array)$class;
echo $classvars["\0SimpleClass\0answer"];
Since php 5.3, one can easily read and write any protected and private member in a object via reflection.
<?php
class fragile {
private $foo = 'bar';
}
$fragile = new fragile;
$ro = new ReflectionObject($fragile);
$rp = $ro->getProperty('foo');
$rp->setAccessible(true);
var_dump($rp->getValue($fragile));
$rp->setValue($fragile, 'haxxorz!');
var_dump($rp->getValue($fragile));
var_dump($fragile);
- Output:
string(3) "bar" string(8) "haxxorz!" object(fragile)#1 (1) { ["foo":"fragile":private]=> string(8) "haxxorz!" }
PicoLisp
PicoLisp uses "transient symbols" for variables, functions, methods etc. inaccessible from other parts of the program. Lexically, a transient symbol is enclosed by double quotes. The only way to access a transient symbol outside its namespace is to search for its name in other (public) structures. This is done by the 'loc' function.
(class +Example)
# "_name"
(dm T (Name)
(=: "_name" Name) )
(dm string> ()
(pack "Hello, I am " (: "_name")) )
(====) # Close transient scope
(setq Foo (new '(+Example) "Eric"))
Test:
: (string> Foo) # Access via method call
-> "Hello, I am Eric"
: (get Foo '"_name") # Direct access doesn't work
-> NIL
: (get Foo (loc "_name" +Example)) # Locating the transient symbol works
-> "Eric"
: (put Foo (loc "_name" +Example) "Edith")
-> "Edith"
: (string> Foo) # Ditto
-> "Hello, I am Edith"
: (get Foo '"_name")
-> NIL
: (get Foo (loc "_name" +Example))
-> "Edith"
Python
Python isn't heavily into private class names. Although private class names can be defined by using a double underscore at the start of the name, such names are accessible as they are mangled into the original name preceded by the name of its class as shown in this example:
>>> class MyClassName:
__private = 123
non_private = __private * 2
>>> mine = MyClassName()
>>> mine.non_private
246
>>> mine.__private
Traceback (most recent call last):
File "<pyshell#23>", line 1, in <module>
mine.__private
AttributeError: 'MyClassName' object has no attribute '__private'
>>> mine._MyClassName__private
123
>>>
Raku
(formerly Perl 6)
We may call into the MOP (Meta-Object Protocol) via the .^ operator, and the MOP knows all about the object, including any supposedly private bits. We ask for its attributes, find the correct one, and get its value.
class Foo {
has $!shyguy = 42;
}
my Foo $foo .= new;
say $foo.^attributes.first('$!shyguy').get_value($foo);
- Output:
42
Ruby
Ruby lets you redefine great parts of the object model at runtime and provides several methods to do so conveniently. For a list of all available methods look up the documentation of Object
and Module
or call informative methods at runtime (puts Object.methods
).
class Example
def initialize
@private_data = "nothing" # instance variables are always private
end
private
def hidden_method
"secret"
end
end
example = Example.new
p example.private_methods(false) # => [:hidden_method]
#p example.hidden_method # => NoMethodError: private method `name' called for #<Example:0x101308408>
p example.send(:hidden_method) # => "secret"
p example.instance_variables # => [:@private_data]
p example.instance_variable_get :@private_data # => "nothing"
p example.instance_variable_set :@private_data, 42 # => 42
p example.instance_variable_get :@private_data # => 42
Scala
class Example(private var name: String) {
override def toString = s"Hello, I am $name"
}
object BreakPrivacy extends App {
val field = classOf[Example].getDeclaredField("name")
field.setAccessible(true)
val foo = new Example("Erik")
println(field.get(foo))
field.set(foo, "Edith")
println(foo)
}
Sidef
Sidef's object model does not enforce privacy, but it allows storing private attributes inside the container of an object, which is an hash:
class Example {
has public = "foo"
method init {
self{:private} = "secret"
}
}
var obj = Example();
# Access public attributes
say obj.public; #=> "foo"
say obj{:public}; #=> "foo"
# Access private attributes
say obj{:private}; #=> "secret"
Swift
Swift reflection provides a Collection of label-value pairs for struct properties
struct Example {
var notSoSecret = "Hello!"
private var secret = 42
}
let e = Example()
let mirror = Mirror(reflecting: e)
if let secret = mirror.children.filter({ $0.label == "secret" }).first?.value {
print("Value of the secret is \(secret)")
}
- Output:
Value of the secret is 42
Tcl
Tcl's object properties are just variables in the a per-instance namespace; all that's required to get hold of them is to discover the name of the namespace concerned:
package require Tcl 8.6
oo::class create Example {
variable name
constructor n {set name $n}
method print {} {puts "Hello, I am $name"}
}
set e [Example new "Eric"]
$e print
set [info object namespace $e]::name "Edith"
$e print
- Output:
Hello, I am Eric Hello, I am Edith
Visual Basic .NET
Like the other .NET languages, VB can use Reflection (Microsoft docs).
Imports System.Reflection
' MyClass is a VB keyword.
Public Class MyClazz
Private answer As Integer = 42
End Class
Public Class Program
Public Shared Sub Main()
Dim myInstance = New MyClazz()
Dim fieldInfo = GetType(MyClazz).GetField("answer", BindingFlags.NonPublic Or BindingFlags.Instance)
Dim answer = fieldInfo.GetValue(myInstance)
Console.WriteLine(answer)
End Sub
End Class
- Output:
42
Wren
In Wren all instance and static fields of a class are private and are prefixed by an underscore and a double underscore respectively. There is no way to break the privacy of such fields that I'm aware of (Wren doesn't have reflection). If one wants to provide public access to fields then this is done via getter and/or setter methods.
However, there is no such thing as a private method. Although conventionally methods which are not intended to be called from outside the class are suffixed with an underscore, this doesn't prevent anyone from accessing them as the following example shows.
class Safe {
construct new() { _safe = 42 } // the field _safe is private
safe { _safe } // provides public access to field
doubleSafe { notSoSafe_ } // another public method
notSoSafe_ { _safe * 2 } // intended only for private use but still accesible externally
}
var s = Safe.new()
var a = [s.safe, s.doubleSafe, s.notSoSafe_]
for (e in a) System.print(e)
- Output:
42 84 84
zkl
In zkl, privacy is more convention than enforced (unlike const or protected).
class C{var [private] v; fcn [private] f{123} class [private] D {}}
C.v; C.f; C.D; // all generate NotFoundError exceptions
However:
C.fcns //-->L(Fcn(nullFcn),Fcn(f))
C.fcns[1]() //-->123
C.classes //-->L(Class(D))
C.vars //-->L(L("",Void)) (name,value) pairs
In the case of private vars, the name isn't saved.
- Object oriented
- Programming Tasks
- Solutions by Programming Task
- ABAP
- Ada
- C sharp
- C++
- Clojure
- Common Lisp
- D
- E
- E examples needing attention
- Examples needing attention
- Ecstasy
- F Sharp
- Factor
- Forth
- FreeBASIC
- Go
- Unicon
- Icon Programming Library
- J
- Java
- Julia
- Kotlin
- Logtalk
- Lua
- M2000 Interpreter
- Nim
- Objective-C
- OCaml
- Oforth
- Perl
- Phix
- Phix/Class
- PHP
- PicoLisp
- Python
- Raku
- Ruby
- Scala
- Sidef
- Swift
- Tcl
- Visual Basic .NET
- Wren
- Zkl
- 6502 Assembly/Omit
- 8086 Assembly/Omit
- 68000 Assembly/Omit
- ARM Assembly/Omit
- AWK/Omit
- BASIC/Omit
- BBC BASIC/Omit
- C/Omit
- Déjà Vu/Omit
- GUISS/Omit
- Haskell/Omit
- Icon/Omit
- Locomotive Basic/Omit
- Lotus 123 Macro Scripting/Omit
- Mathematica/Omit
- Rust/Omit
- R/Omit
- SmileBASIC/Omit
- Standard ML/Omit
- X86 Assembly/Omit
- Z80 Assembly/Omit
- Zig/Omit
- ZX Spectrum Basic/Omit
- Insitux/Omit