GVKun编程网logo

PHP 类与构造函数解析(php类的构造函数)

17

在这里,我们将给大家分享关于PHP类与构造函数解析的知识,让您更了解php类的构造函数的本质,同时也会涉及到如何更有效地C#构造函数、私有构造函数、静态构造函数与构造函数执行顺序、java–构造函数参

在这里,我们将给大家分享关于PHP 类与构造函数解析的知识,让您更了解php类的构造函数的本质,同时也会涉及到如何更有效地C#构造函数、私有构造函数、静态构造函数与构造函数执行顺序、java – 构造函数参数解析、javascript – “构造函数”函数,不应与构造函数调用一起使用、JavaScript构造函数解析的内容。

本文目录一览:

PHP 类与构造函数解析(php类的构造函数)

PHP 类与构造函数解析(php类的构造函数)

----类的创建----

PHP使用关键字class创建一个类,并且使用一对大括号

如:

n=$newn;//this表示这个类 } }

结尾不打分号。则$n,$u为字段;name()为构造函数(__construct()也可定义构造函数,详见下文),可以为字段赋值;rename()为方法。

----字段与方法----

比较

n;

u;

前者可执行,后者不可因为$u前声明了私有private。这一点是与c++类似的。

代码:

rush:PHP;"> public static $nm ="2333333333333333" ;

为函数申明了一个静态字段。

通过类名与::可以直接访问该变量

rush:PHP;"> echo name::$nm;

这一点也是与c++类似的。

PHP中还可以通过 self::+$+变量名 在类中访问静态字段,这时self相当于$this->。

----构造函数----

在PHP5和早期版本中构造函数与类同名

在PHP5和之后的版本中魔术字 __construct() 可定义构造函数

n=$newn; } }

构造函数可有参数

rush:PHP;"> __construct($name="",$sex="man",$age=0){}

在申明对象时

rush:PHP;"> $obj= new name("我","man",28);

这时如果没有给出参数,则默认为=后的值。

以上所述是小编给大家介绍的PHP 类与构造函数解析,希望对大家有所帮助。程序员遇到问题都会上(小编jb51.cc)查找问题解答方法!如果觉得站点还不错,随手转发给程序员朋友一下!

C#构造函数、私有构造函数、静态构造函数与构造函数执行顺序

C#构造函数、私有构造函数、静态构造函数与构造函数执行顺序

https://www.cnblogs.com/ArtofDesign/p/3603986.html

 默认构造函数,如果没有为类指定任何构造函数,编译器会自动为类创建一个无参构造函数,用以初始化类的字段;如果为类编写了构造函数,那么编译器就不会再自动生成无参构造函数了。ps.C#不允许用户为结构定义无参构造函数。

 

    静态构造函数,不能访问实例成员,只能用来初始化一些静态字段或者属性,仅在第一次调用类的任何成员时自动执行,不带访问修饰符,不带任何参数,每个类只能有一个静态构造函数,但可以同时还有一个无参实例构造函数,如下。

public class Demo
{
    static Demo() { }
    public Demo() { }
}

   

    私有构造函数,将构造函数申明为私有的,则不能通过new运算符在外部代码中实例化(但可以编写一个静态方法或属性在其内部实例化一个对象,再将结果返回给外部代码)。私有构造函数的作用:

  • 永远不会实例化,因为它仅用作某些静态成员的容器
  • 希望类只能通过调用某个静态方法来实例化(即所谓的对象实例化的类工厂方法)
复制代码
public class Demo
    {
        private Demo() { }
        public static Demo NewDemo()
        {
            return new Demo();
        }
    }
复制代码

 

    构造函数执行顺序,通常情况下:构造函数先调用System.Object的构造函数,再按照继承的层次结构从上往下进行,直到最终要实例化的类为止,即最先调用的是基类的构造函数,但如果类有静态构造函数,且为首次调用该类,则先调用的是子类的静态构造函数,再是父类的静态构造函数,当然静态构造函数只会执行这一次,如下

复制代码
//父类
public class SuperClass
{
    static SuperClass() 
    {
        Console.WriteLine("Super.Static");
    }
    public SuperClass() 
    {
        Console.WriteLine("Super.Instance");
    }
}

//子类
public class ChildClass : SuperClass
{
    static ChildClass() 
    {
        Console.WriteLine("Child.Static");
    }
    public ChildClass() 
    {
        Console.WriteLine("Child.Instance");
    }
}

//客户程序
class Program
{
    static void Main(string[] args)
    {
        ChildClass cc = new ChildClass();
        Console.ReadKey();
    }
}
复制代码

输出结果为:

Child.Static

Super.Static

Super.Instance

Child.Instance

 

    在不考了静态构造函数的情况下(因为静态构造仅执行一次,且定义静态构造函数的时候并不多),子类在调用父类的构造函数时,默认情况是调用父类的无参构造函数,如果父类只有带参构造函数,而没有无参构造函数,那么编译时会报错;不过我们可以通过base关键字来指定调用带参构造函数,如下

复制代码
//父类
public class SuperClass
{
    public SuperClass(string param)
    {
        Console.WriteLine("Super:" + param);
    }
}

//子类
public class ChildClass : SuperClass
{
    public ChildClass(string param):base(param)
    {
        Console.WriteLine("Child:" + param);
    }
}

//客户程序
class Program
{
    static void Main(string[] args)
    {
        ChildClass cc = new ChildClass("param");
        Console.ReadKey();
    }
}
复制代码

输出结果为

Super:param

Child:param

public class SuperStaticConstructor
    {
        public SuperStaticConstructor()
        {
            Console.WriteLine("parent constructor");
        }

        static SuperStaticConstructor()
        {
            Console.WriteLine("parent static constructor");
        }
    }
    public class StaticConstructor: SuperStaticConstructor
    {
        public StaticConstructor()
        {
            Console.WriteLine("child constructor");
        }

        static StaticConstructor()
        {
            Console.WriteLine("child static constructor");
        }
    }

    public class StaticConstructorTest
    {
        public static void Run()
        {
            string[] strArray = new string[4]{ "a","b", "a", "b" };
            Parallel.ForEach(strArray, (item) =>
            {
                Console.WriteLine(item);
                new StaticConstructor();
            });
        }
    }

  StaticConstructorTest.Run();

 

java – 构造函数参数解析

java – 构造函数参数解析

我最近开始在3.2版本上工作.我试图理解构造函数参数解析,以防何时通过构造函数注入传递依赖项.我创建了以下示例.

package com.springinaction.springidol;

public interface Performer {
    void perform();
}
package com.springinaction.springidol;

public class Juggler implements Performer {

    private int beanBags=3;
    private String name;

    public Juggler(){
    }

    public Juggler(String name,int beanBags){
        System.out.println("First constructor gets called");
        this.beanBags=beanBags;
        this.name=name;
    }

    public Juggler(int beanBags,String name){
        System.out.println("Second constructor gets called");
        this.beanBags=beanBags;
        this.name=name;
    }

    public void perform(){
    System.out.println("JUGGLING "+beanBags+name+" BEANBAGS");
    }
}

请查看下面我使用的spring配置文件的实例.

<?xml version="1.0" encoding="UTF-8" ?>

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

<bean id="duke">
    <constructor-arg value="Jinesh" />
    <constructor-arg value="77" />
</bean>

在上面的场景中,调用的构造函数是第一个构造函数.但之后我稍微更改了xml文件并为两个参数添加了type属性.

<?xml version="1.0" encoding="UTF-8" ?>

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

<bean id="duke">

<constructor-arg type="java.lang.String" value="Jinesh" />
<constructor-arg type="int" value="77" />

</bean>

</beans>

在上面的例子中,spring调用的构造函数是第二个构造函数.我不明白为什么spring决定调用第二个构造函数而不是第一个构造函数?在上面的例子中,当我们传递type属性时spring如何决定调用哪个构造函数?

解决方法

Spring使用ConstructorResolver实例来解析用于实例化类的构造函数.它调用autowireConstructor()方法来确定它.您可以在线找到源代码.旧版本,here.如果您有源(使用maven),您可以自己调试并完成它.

在该方法中,它尝试使用ArgumentsHolder#getTypeDifferenceWeight()方法确定指定参数与控制器中参数之间的差异.在我们的例子中,它将返回值0,因为参数匹配(即使是以不同的顺序).

该值与minTypeDiffWeight值(最初为Integer.MAX_VALUE)进行比较.如果它更小,则被评估的当前构造函数将获得优先级,并且该值将替换minTypeDiffWeight.这个方法通过所有Class’构造函数继续进行,再次与minTypeDiffWeight进行比较.由于两个构造函数都将赋值0(0不小于0),因此使用找到的第一个.

正好

Juggler.class.getDeclaredConstructors();

返回一个类似的数组

[public Test.Juggler(int,java.lang.String),public Test.Juggler(java.lang.String,int),public Test.Juggler()]

其中第二个(声明的)构造函数首先出现. getDeclaredConstructors()方法javadoc声明

The elements in the array returned are not sorted and are not in any
particular order.

所以这只是巧合.因为参数类型匹配,所以Spring选择它在该数组中找到的第一个构造函数.

javascript – “构造函数”函数,不应与构造函数调用一起使用

javascript – “构造函数”函数,不应与构造函数调用一起使用

(完整代码在 this github repo)

在You don’t know JS系列丛书(特别是“this& Object Prototypes”标题)以及许多SO答案(例如this one)中,经常会发现没有“构造函数”这样的东西,而是通过调用的普通函数. “构造函数调用”.我试图通过创建vanilla函数来解决这一问题,这些函数并不是用new来调用来创建我的对象.

第一次尝试有效:

var assert = function(condition,message) {
    if (!condition)
        throw new Error(message||'assertion error');
};

var Counter1 = function() {
    var count = 0;
    return {get: function() {return count;},inc: function() {count++;}};
};

var c2a = Counter1();
c2a.inc();
assert(c2a.get()===1);
var c2b = Counter1();
assert(c2b.get()===0);
assert(c2a.get()===1); // prevIoUs counter is a separate object

现在我试图通过不每次重新创建getter / setter函数来改进上面的代码,而只是简单地将它们分配给原型(这里我失败了):

var Counter2 = function Counter2_() {
    var count = 0;
    Counter2_.prototype.get = function() {return count;};
    Counter2_.prototype.inc = function() {count++;};
    assert(Counter2_.prototype.constructor === Counter2_);
    var rv = {};
    rv.__proto__ = Counter2_.prototype;
    return rv;
};

var c = Counter2();

c.inc();
assert(c.get()===1);
assert(Object.getPrototypeOf(c)===Counter2.prototype);

var cb = Counter2();
assert(Object.getPrototypeOf(cb)===Counter2.prototype);
assert(cb.get()===0);
assert(c .get()===1,'expecting c to be 1 but was:'+c.get());

上面的代码在最后一行失败了.
我的理解是上面的代码没有成功维护单独的计数器,因为每次调用Counter2函数时,先前对象的原型get被设置为新创建的函数,该函数在词法上绑定到新计数(再次初始化为0).此外,代码是愚蠢的,因为每次调用Counter2函数时都会再次创建函数,并在原型上反复重新分配(带来的灾难性结果是无法维护单独的计数器).

然而,尝试将分配放置在Counter2函数之外的原型也会失败,因为count变量不再在范围内:

var Counter3 = function Counter3_() {
    var count = 0;
    var rv = {};
    rv.__proto__ = Counter3_.prototype;
    return rv;
};

Counter3.prototype.get = function() {return count;}; // this fails - I no longer have access to count's lexical scope
Counter3.prototype.get = function() {return this.count;}; // this fails too

我的问题是:

1)我的解读为什么Counter2无法保持单独的计数器正确?

2)有没有办法使用这个习惯用法(即使用不想用new调用的“vanilla”函数),并且每次调用函数时都避免重新创建getter / setter?

解决方法

1)是的,每次重新定义原型的get和inc.原型不是“封闭”的,原型继承的链式行为使这成为可能.

function Counter2(name) {
    var count = 0;

    Counter2.prototype.get = function() {return count;};
    Counter2.prototype.inc = function() {count++;};

    var rv = {};
    if(name) {
        rv.get = function() {console.log(name); return count;};
    }
    console.log(count)
    rv.__proto__ = Counter2.prototype;
    return rv;
}

var a = Counter2('a');
var b = Counter2('b');
var c = Counter2();

在下面的示例中,a和b不继承get函数,因为它们的get键未定义并指向不同的函数实例.请记住,如果传入一个名称,并且每次猜到以下输出将被重新定义时,计数变量仍然会被分配和唯一绑定.

a.inc();a.inc();
[a.get(),b.get(),c.get()]

是:

  [0,2]

2)是和否.您可以轻松返回具有每次都不会分配的函数的对象,但如果绑定了变量,它们将在它们之间共享.奇怪的是,通过使用原型继承和新的运算符,这可以很容易地完成.

例如,以下代码不会每次都分配新函数,但a.inc()将增加b的值,如果调用则增加其他值.

var count = 0;

function inc() {++count;}
function get() {return count;}

function Count() {
    return {inc: inc,get: get};
};

var a = Count();
var b = Count();

通过使用new运算符,可以实现唯一绑定的“变量”,而无需每次都分配新函数.

function Count(){}
    Count.prototype.count = 0;
    Count.prototype.get = function() {return this.count;};
    Count.prototype.inc = function() {this.count++;};

var a = new Count();
var b = new Count();
a.inc();
a.get();
>>1
b.get();
>>0
a.inc === b.inc
>>true

JavaScript构造函数解析

JavaScript构造函数解析

构造函数的原理
javascript语言是一门面向对象的语言,但是javascript中并没有类的概念的。于是javascript采用构造函数的方式来模拟类的效果,即我们通过函数来创建对象。这也证明了函数在javascript中具有非常重要的地位。举个例子:


        var Book = function(name, price) {
          this.name = name;
          this.price = price;
        }

        var java = new Book(''Master Java'', 82);
     
当使用new关键字来调用构造函数时,执行上下文从全局变量对象(window)变成一个空的上下文,这个上下文代表了新生成的实例。因此,this关键字指向当前创建的实例

默认情况下,如果你的构造函数中没有返回任何内容,就会返回this----当前的上下文,也就是你当前创建的对象。要不然就返回任意非原始类型的值。而普通的函数如果没有明显的返回值将返回undefined。

模拟构造函数创建对象
其实使用new创建一个对象的过程并不神秘,我们可以使用代码来模拟如何创建一个对象:

立即学习“Java免费学习笔记(深入)”;


        var Book = function(name) {
          this.name = name;
        };

        //正常用法
        var java = new Book(‘Master Java’);
       
        //使用代码模拟,在非IE浏览器中测试,IE浏览器不支持
        var python = {};
        python.__proto__ = Book;
        Book.call(python, ''Master Python'');
     
将构造函数作为普通函数调用
实际上构造函数就是个普通的函数,可以当作普通函数调用的,例如var result = Book();,当然结果是undefined。区别在于函数中this的指向。我们重新修改一下上面的构造函数,


        var Book = function(name, price) {
        this.name = name;
        this.price = price;
        if (this == window) {
          return ''name = '' + name + ", price = " + price;
        }
      }
     
这样当执行var result = Book("Java", 100)的结果是"name = Java, price = 100", 而var java = new Book("Java", 100)的结果就是创建了一个新的对象。JavaScript自带的构造函数好多就是既当普通函数又当构造函数的。比如String和Number,当String和Number作为构造函数来使用时,


        var a = new Number(11);
        var b = new Number(11.222);
        var c = new String("hello");
     
当String和Number作为普通函数来使用时,他们可以用来作类型转换,即Number函数可以将其它类型转换为number类型,String函数可以将其它类型转换为字符串,


        var a  = Number(''11''); //11
        var b = Number(''hello''); //NaN
        var c = String(11); //''11''
        var d = String(null); //''null''
     
总结
当一个函数要作为构造函数使用时通常将函数名首字母大写表示这是个构造函数,同时,一定要用new去调用构造函数。另外尽量不要把构造函数做普通函数使用,因为容易产生全局变量,同时如果处理不好返回值容易对构造函数自身的功能产生影响。

关于PHP 类与构造函数解析php类的构造函数的问题我们已经讲解完毕,感谢您的阅读,如果还想了解更多关于C#构造函数、私有构造函数、静态构造函数与构造函数执行顺序、java – 构造函数参数解析、javascript – “构造函数”函数,不应与构造函数调用一起使用、JavaScript构造函数解析等相关内容,可以在本站寻找。

本文标签: