Is it possible to make a field of a record private? or to make a member of record private?

早过忘川 提交于 2019-12-19 02:05:09

问题


I want to stick with record, and don't want to go back to object. So I am wondering if it is possible to make a field of a record private? or to make a private member of record. what about other concrete types such as discriminated union?

Or, does this requirement violate the language spec?


回答1:


Nope, it's not possible for single fields to be private: http://msdn.microsoft.com/en-us/library/dd233184

However, you can make all fields private and expose selected fields through properties. Note that you will need a Create-function in order to create an instance of the records, since its' fields are private:

type MyRec = 
    private
        { a : int
          b : int }
    member x.A = x.a
    member private x.Both = x.a + x.b  // Members can be private
    static member CreateMyRec(a, b) = { a = a; b = b }

Members can be private though, as in the case of the MyRec.Both property above.

Edit: The above makes the fields private to the module that MyRec is defined in, not private to MyRec. See Daniel's answer to Weird accessibility scopes when F# record's fields are declared private.




回答2:


The problem with this requirement is that the language features of record require the properties to be public. For example if you have a record r of type R with properties Name and Age and write
{ r with Age = 20 }, the compiler turns that into new R(r.Name, 20).

The idea is that with copies all properties (excluding the one you want to change) and so it needs to be able to access them. For this, the compiler could actually generate methods for every possible with use, but that could generate a lot of methods.

What are your reasons for prefering records? They have two nice features - the with keyword (which you lose with private members anyway) and structural equality (two instances are the same when they have the same values). Aside from that, classes seem to be easier to use, if you want to hide some fields.

Here is a simple example (which does not implement strucural equality):

type R(name:string, age:int) = 
  member x.Name = name
  member x.WithAge(newAge) = R(name, newAge)

Using records with private fields seems fine - although it may make more sense to use public fields within an implementation file and an F# signature file that hides the fields for all external users. This way, you can use features like with in the implementation, but still hide the type.




回答3:


I don't think it's possible. MSDN says:

Record fields differ from classes in that they are automatically exposed as properties, and they are used in the creation and copying of records. Record construction also differs from class construction. In a record type, you cannot define a constructor.

"Automatically exposed" is a key to answer your question. Is three any reason why you don't want to create a new type?



来源:https://stackoverflow.com/questions/12389308/is-it-possible-to-make-a-field-of-a-record-private-or-to-make-a-member-of-recor

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!