精华内容
下载资源
问答
  • 需求: 有一个Child类是一个data类, 继承一个父亲类Parent , 从而在Child中公用父亲某些参数. 这在java中是很容易实现的, 但是在Kt中由于需要用到data类(后期需要做gson转换), 在处理构造函数遇到了问题 . ...

    最近刚刚接触Kt,, 昨天使用Kt的时候遇到构造函数中 val var 使用的一个问题,  虽然昨天功能完成了, 但是还是有些糊涂, 为避免以后再遇到此类问题导致浪费时间, 现把原理介绍一下.

    需求: 有一个Child类是一个data类, 继承一个父亲类Parent , 从而在Child中公用父亲某些参数.  这在java中是很容易实现的, 但是在Kt中由于需要用到data类(后期需要做gson转换), 在处理构造函数遇到了问题 .

    103504_uev1_259459.png

     

    1. 刚开始, 我定义Parent是data类, 但是data类是final的, 所以没法被孩子继承, 失败

    2.那只能定义Parent为class, Child 是data

    open class Parent(weight: Int, height: Int)
    data class Child(var grade: Int, var weight: Int, var height: Int) : Parent(weight, height)

    这里有问题了 为什么父亲没有var val, 孩子有var val呢? 那能不能去掉吗? 

    当然data是不能去掉 var/val的, 去掉以后会报 data class must have only property (var/val) parameters

    那Parent能不能加上var或者val呢? 通过转换为java代码看一下:

    1.Base构造函数没有var val

    open class Base(num: Int)

    java

    public class Base {
       public Base(int num) {
       }
    }

    Base构造函数有val

    public class Base {
       private final int num;
    
       public final int getNum() {
          return this.num;
       }
    
       public Base(int num) {
          this.num = num;
       }
    }

    Base构造函数有var 

    public class Base {
       private int num;
    
       public final int getNum() {
          return this.num;
       }
    
       public final void setNum(int var1) {
          this.num = var1;
       }
    
       public Base(int num) {
          this.num = num;
       }
    }

     

    其实var 其实就是在编译的时候为代码加上 getter 和setter 方法, val是只读, 只加上getter方法

    不加var, val 就不会生成任何getter和setter了.

    这些getter setter 都是final的.

    如果Base中有了getter setter, 子类data class中也有了同一字段的,  getter setter那就冲突了

     

    总结:

    1.val var 就是为形参加上 final的 getter. setter

    2.KT 遇到问题通过转换为java代码, 可以很快找到答案

    转载于:https://my.oschina.net/sfshine/blog/1800812

    展开全文
  • 参数继承

    2020-06-19 23:47:42
    参数分为形参和实参 形参出现在函数定义中,在整个函数体内都可以使用, 离开该函数则不能使用。 实参出现在主调函数(也就是main)中,进入被调函数后,实参变量也不能使用形参举例: 继承 extends 继承就是...

    参数分为形参和实参
    形参出现在函数定义中,在整个函数体内都可以使用, 离开该函数则不能使用。
    实参出现在主调函数(也就是main)中,进入被调函数后,实参变量也不能使用。
    形参举例:
    在这里插入图片描述
    继承 extends
    继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。当子类想调用父类方法时,需要用到super()关键字。由super()中的参数去寻找父类中的方法。子类构造器默认的调用父类无参构造器,即子类构造器没有用super指明调用父类那个构造器的话,自动调用无参。
    在这里插入图片描述
    当类的类型为public时,同一包下的类想要调用其方法时,可直接用类名.方法名调用。
    在这里插入图片描述
    在这里插入图片描述
    方法体中不仅有参数,还有返回值修饰,有返回值用void修饰,无返回值就不用void,就在方法内return+要返回的值
    在这里插入图片描述
    子类继承父类所有的成员变量和成员方法。
    子类在继承父类方法和属性的同时也可对父类方法进行重写和重载。继承默认继承object父类。
    一旦显示定义了构造方法,则系统不在提供默认构造方法。
    对Java对象的强制类型转换称为造型。从子类到父类的类型转换可以自动进行;从父类到子类的类型转换必须通过造型(强制类型转换)实现;无继承关系的引用类型间的转换是非法的;在造型前可以使用instanceof操作符测试一个对象的类型
    上溯造型:子类转换成父类,自动转换。向上转换损失了子类新扩展的属性和方法,仅可以使用从父类继承的方法
    在这里插入图片描述
    下溯造型:(强制转换)将父类对象显示转换成子类类型。曾经向上转换过的对象才能向下转换。对象不允许不经过上溯造型而直接下溯造型。
    在这里插入图片描述
    当我们进行下溯造型时,需要判断是哪个子类型,否则容易出现异常,这个时候就需要用到instanceof运算符来帮助我们判断经过上溯造型后是哪一个子类的。
    在这里插入图片描述

    重写:不改变方法参数和修饰,改变方法里的内容
    重载:不改变方法的名称,但改变方法的参数
    子类继承父类属性举例:
    在这里插入图片描述
    在这里插入图片描述

    重写举例:
    在这里插入图片描述
    在这里插入图片描述
    重载举例:

    展开全文
  • 真是种奇妙的多态实现方式,可以把其理解成一个抽象类,让形参接受具体的函数实现,然后让这个形参再去调用对应的函数,从而实现一个方法多种使用。 面向接口的编程,通过接口的抽象能减少类之间的耦合,增加可复用...

    按照以前的经验,形参一般都是基础变量,或者class之类的,都比较常规。

    最近工作中,见了一种以前没见过的写法,记录下我的思考

    java的接口只有一堆定义好形参和返回值的方法名。我们常用接口去定义一种行为模式,然后再去由各自子类去实现方法,从而实现继承多态。

    但如果把接口作为函数的参数呢?
    真是种奇妙的多态实现方式,可以把其理解成一个抽象类,让形参接受具体的函数实现,然后让这个形参再去调用对应的函数,从而实现一个方法多种使用。

    面向接口的编程,通过接口的抽象能减少类之间的耦合,增加可复用性

    试想我们面临这样的场景,我们有一个对象,然后不同的业务期望对对象做不同的事。

    常规下可能会写一个抽象业务类,包含事物处理的抽象函数,然后新的业务去继承这个类,然后实现业务的处理。
    那如果事物的处理其实有着不少相似之处,只是步凑或者少量不同呢,就再抽象出相同的处理函数,再在各自的事物处理实现函数中去调用。

    如果期望异步的处理业务,那就需要个事件队列,业务只负责把自己的业务放进去,让消费者去处理。
    但这个队列和消费者的实现无疑是麻烦的

    但可以这样做,做成一个接口列表,为不同事件写好接口实现,每次只用add进去一个接口实现,后续消费者也只用统一调用接口里的方法就行。
    而新增业务或和更改业务只用在自己这边改动就好,中间的队列和消费者则不用改动,减少类之间的耦合,增加可复用性。

    比如这样

    interface inter{
    	public void hello();
    }
     
    public class interlist implements inter{
        private List<inter> inters = new ArrayList<inter>();
    	private int i=0;
        public void addinter(inter i) {
            inters.add(i);
        }
        public void hello() {
           System.out.println("hello list");
           //统一消费它们
           for(;i<inters.size();i++){
           	inter in= inters.get(i);
           	in.hello();
           }
        }
    }
    public class yewua{
    	//业务a
    	public void realize_a(interlist ilist){
    		ilist.addinter(new inter{
    			public void hello(){
    				System.out.println("hello yewua_realize");
    			}
    		});
    	}
    }
    public class yewub {
    	//业务b
    	public void realize_b(interlist ilist){
    		ilist.addinter(new inter{
    			public void hello(){
    				System.out.println("hello yewub_realize");
    			}
    		});
    	}
    }
    public static void main(String[] args) {
    	interlist myinterlist=new interlist();
    	yewua a;
    	a.realize_a(myinterlist);
    	yewub b;
    	b.realize_b(myinterlist);
    
    	//消费它们
    	myinterlist.hello();
    }
    

    我定义了接口inter和一个函数hello,并定义了一个接口列表interlist,业务yewua和yewub只用在自己的实现中把inter的实现放入列表中即可。
    后续逻辑再统一消费它们,myinterlist.hello();

    输出如下:

    hello list
    hello yewua_realize
    hello yewub_realize

    如果我需要更改需求,让业务a输出hello new_yewua
    只需更改

    public void realize_a(interlist ilist){
    		ilist.addinter(new inter{
    			public void hello(){
    				System.out.println("hello new_yewua");
    			}
    		});
    	}
    

    其他不用改动,输出如下:

    hello list
    hello new_yewua
    hello yewub_realize

    以上小例可以看出其好处了

    展开全文
  • 非信用形参包括: 1)普通形参 ①非const形参 ②const形参 2)指针形参 ①非const指针形参 ②const指针形参 一、下面的例子说明了非引用形参的传参实例! #include<iostream> #include<string> #include...

    非信用形参包括:
    1)普通形参
    ①非const形参
    ②const形参
    2)指针形参
    ①非const指针形参
    ②const指针形参

    一、下面的例子说明了非引用形参的传参实例!

    #include<iostream>
    #include<string>
    #include<stdlib.h>
    #include<vector>
    using namespace std;
    
    void AddOne(int x)//非指针参数:非引用形参---就是copy(拷贝)
    {
    	x = x + 1;//这里实际是吧copy加一!!
    }
    
    
    //这里也是传递的是copy,但是是指针的copy,因此也能间接实现引用传递的功能
    void AddTwo(int *px)//非引用形参:指针形参
    {
    	*px = *px + 2;
    }
    
    void AddThree(int& x)//参数:引用形参
    {
    	x = x + 3;//真正对传进来的实参进行加法
    }
    int main()
    {
    	int a, b, c;
    	a = 1;
    	b = 2;
    	c = 3;
    	cout << "加之前:" <<a<< endl;
    	//并没有把 真正的a传进去,传进去的a是copy
    	AddOne(a);
    	cout << "加之后:" <<a<< endl;
    
    	system("pause");
    }
    

    大部分的盆友可能乍一看会觉得加之后的a是2,其实不然,我们来看下结果
    在这里插入图片描述
    惊不惊喜,a还是2,因为所有的非引用参数在传递的时候其实是把实参的copy传递进去了,并没有把真正的实参传进去,因此在函数体中确实完成了加一的操作,但是却是对实参的copy进行操作,真正的函数外面的实参并没有变化!

    那么我们在来看引用形参的实际传递情况!!

    int main()
    {
    	int a, b, c;
    	a = 1;
    	b = 2;
    	c = 3;
    	cout << "加之前:" <<a<< endl;
    	//并没有把 真正的a传进去,传进去的a是copy
    	AddOne(a);
    	cout << "加之后:" <<a<< endl;
    
    
    	cout << "加之前:" << c << endl;
    	//传的是真正的c,不是c的copy
    	AddThree(c);
    	cout << "加之后:" << c<< endl;
    	system("pause");
    }
    

    运行结果如下:
    在这里插入图片描述
    那么我们使用非引用形参的指针形参效果又如何呢?

    来看一下代码:

    int main()
    {
    	int a, b, c;
    	a = 1;
    	b = 2;
    	c = 3;
    	cout << "非引用形参:非指针形参*************************************" << endl;
    	cout << "加之前:" <<a<< endl;
    	//并没有把 真正的a传进去,传进去的a是copy
    	AddOne(a);
    	cout << "加之后:" <<a<< endl;
    	cout << "非引用形参:指针形参*************************************" << endl;
    	cout << "加之前:" << b << endl;
    	//并没有把 真正的a传进去,传进去的a是copy
    	//把b的地址copy一个传进去,也会间接修改真正的b
    	AddTwo(&b);
    	cout << "加之后:" << b << endl;
    	cout << "引用形参*************************************" << endl;
    	cout << "加之前:" << c << endl;
    	//传的是真正的c,不是c的copy
    	AddThree(c);
    	cout << "加之后:" << c<< endl;
    	system("pause");
    }
    

    结果如下:
    在这里插入图片描述
    我们可以发现,好像使用指针形参也能实现对实参b的真正修改,其中的原理就是:这里因为是非引用形参只能传递copy,因此它会把b的地址copy一个进来,但是地址的拷贝还是原来的地址,因此对地址的操作就是对真正的b进行操作!!

    二、接下来再看一个例子

    #include<iostream>
    #include<string>
    #include<stdlib.h>
    #include<vector>
    using namespace std;
    
    int add(int x, int y)//形参是非const的
    {
    	return x + y;
    }
    
    int add_2(const int x, const int y)//形参是const的
    {
    	return x + y;
    }
    
    int main()
    {
    	int a, b, c;
    	const int m = 8, n = 9;//这里需要注意的是const变量只能在定义的同时给其赋值!!
    	a = 1;
    	b = 2;
    	c = 3;
    	//用非const变量传递到非const形参的函数中**********************
    	int k = add(a, b);
    	cout << k << endl;
    
    	//用非const变量传递到非const形参的函数中***********************
    	k = add(m, n);
    	cout << k << endl;
    	system("pause");
    }
    

    在这里插入图片描述
    可以看到结果,尽管是const变量传递到非const形参的函数中是可以允许的,反之也是允许的!

    那么const 形参的目的和好处是什么呢?
    让我们来看一个函数

    void addOne(const int x)
    {
    	x = x + 1;//传进来的x不能修改,因为是const
    }
    

    如果形参是const,那么意味着传进来的实参的copy(因为这里是非引用形参)就不能修改了,因此只要不进行对形参的修改,非const的实参也是可以传递它的copy进来!!,就比如上面的add_2函数

    当然尽管形参是一个const的指针,也是不能修改的,因为该指针指向的是一个const的常量值

    void AddOne(int *ip)//这样允许修改
    {
    	*ip = *ip + 1;
    }
    
    void AddTwo(const int *ip)//这样不允许修改
    {
    	*ip = *ip + 2;
    }
    
    int Add(const int *px,const int *py)
    {
    	return *px+*py;//这样的运算是可以被允许的
    }
    

    上面我们说到,一个const的实参传递到非const形参的函数中是被允许的,但是一个const的指针实参传递到非const指针形参的函数中是不被允许的,实例如下:

    #include<iostream>
    #include<string>
    #include<stdlib.h>
    #include<vector>
    using namespace std;
    
    int add(int x, int y)//形参是非const的
    {
    	return x + y;
    }
    
    int add_2(const int x, const int y)//形参是const的
    {
    	return x + y;
    }
    void AddOne(int *ip)
    {
    	*ip = *ip + 1;
    }
    
    int Add(const int *px, const int *py)
    {
    	return *px + *py;//这样的运算是可以被允许的
    }
    int main()
    {
    	int a, b, c;
    	const int a2 = 10, b2 = 20, c2 = 30;
    	a = 1;
    	b = 2;
    	c = 3;
    	AddOne(&a);//非const int *  可以传给   非const int *
    	//AddOne(&a2);//const int *  不可以传给  非const int *
    	Add(&a, &b);//非const int *  可以传给   const int *
    	Add(&a2, &b2);//const int *  可以传给   const int *
    	system("pause");
    }
    

    因此可以列一个表格表示

    非指针形参指针形参
    Non-const->const(允许)Non-const->const(允许)
    const->const(允许)const->const(允许
    Non-const->const(允许)Non-const->Non-const(允许)
    const->Non-const(允许)const->Non-const(不允许)

    还有一点需要注意的是:
    在C++语言中,继承了C语言的规定,认为const的非指针形参和非const的非指针形参是一样的,因此在使用函数重载的时候需要格外注意:

    void fcn(int i) {}
    void fcn(const int i) {}
    

    这样是无法实现重载的!!!

    三、非引用形参的局限性

    1、想要修改某个值就没法实现,除非是用指针形参!
    2、如果需要传递的实参数据很庞大,那么在使用非引用形参函数的时候,需要完全拷贝,这样做的时间和空间浪费的代价是很大的!

    展开全文
  • 继承参数传递及调用顺序

    千次阅读 2014-11-09 14:29:15
    继承参数传递及调用顺序 一、简单派生类的构造函数传参 C++语言的继承特性,指子类可以继承父类的属性和行为,并可以重新定义或添加新的属性和行为。父类中为private型的属性和行为虽然被继承,但是子类中仍不...
  • 今天见了一种很奇怪的写法,以前没有见到过,所以做个小记录,供以后思考使用。 在我的印象中,java的接口是不可以实例化的,也就是说没有构造器,没有属性,只有一堆定义好形参和返回值的方法名。不能在程序中用...
  • 子程序参数 ... 如果想子程序拥有参数,需要在子程序的头部声明形参。在每个形参的声明中需要指定名称和数据类型,指定模式和默认值。后2者是可选的。在子程序的执行部分通过名称来引用形参。 ...
  • 如题,有一个方法里两个形参,我另一个文件类中一个方法想要那个方法的返回值,可是第二个参数在这里用不到,能否只传第一个参数 如何实现,前提这个类不能继承后重写方法,因为多人合同写的。
  • Class object = Model.class; //Method[] methods = ...//所有方法,包括继承Object的 Method[] methods = object.getDeclaredMethods();//自己的public方法 for(Method one:methods) { System.out.print(one.g...
  • C++中函数的形参主要有两种类型: 非引用形参和引用形参, 对应两种不同的参数传递方式。 void f(int t); void f(int &t); 非引用行参是实参的一个副本, 故对非引用形参的修改不会影响实参; 引用形参是实参的...
  • 派生类的构造函数受继承关系的影响,每个派生类构造函数除了初始化自己的数据成员之外,还要初始化基类。 派生类的合成默认构造函数:除了初始化派生类的数据成员之外,它还初始化派生类对象的基类部分。基类部分 由...
  • 永远不要重新定义虚函数继承的默认缺省参数,因为虚函数具有动态绑定特性但是默认缺省参数却具有静态绑定特性。 如果重新定义了默认参数,就会出现混乱,比如下面程序: #include using namespace std; class ...
  • OC继承详解与使用规则

    千次阅读 2015-08-15 09:07:45
    2、继承使用场合: (1)如果有两个或者两个以上的类含有很多相同的成分(成员变量/方法相同)。那么就可以把它们相同的部分提取到一个单独的类中,让这些相似的类继承于它。继承的实质就是把多个类中相同的代码抽...
  • 私有继承派生类使用基类的成员函数 题目: 1、定义一个Animal类,成员包括: (1)整数类型的私有数据成员m_nWeightBase,表示Animal的体重; (2)整数类型的保护数据成员m_nAgeBase,表示Animal的年龄; (3...
  • 你见过接口类型数组做形参吗?为啥用接口类型做形参,有啥好处?且随我往下看 目录示例优点相关设计模式 示例 github:demo地址 package interfaceArray; public interface Pet { /** * 动物跑步 */ public ...
  • 如果一个类继承泛型类(或者实现了泛型接口),就必须为基础类型的泛型形参指定一个泛型实参。它可以是具体的类型或者另一个类型形参 。所以你会发现ArrayList 中的T和List中的T实际上有所不一样的,就是类型形参和...
  • 标题有点拗口难懂,用代码来说比较... // 基类中定义一个虚方法 ExecuteNonQuery,用以执行一段 SQL 查询,并传递一个参数 public virtual int ExecuteNonQuery(string Query, DbParameter Parameter) { return 1;
  • Item 37:绝不重新定义继承而来的缺省参数
  • 函数的参数 [函数的参数](重要)(https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/001431752945034eb82ac80a3e64b9bb4929b16eeed1eb9000) 什么叫可变对象和不可变对象 、...
  • C++继承介绍

    2020-12-31 09:19:43
    然后是各个成员函数选项可以是virtual或non-virtual或pure virtual。本文仅仅作出一些关键点的验证。...下面是验证代码,一个参数为base的函数,传入derived应该成功执行,相反,一个参数为derived
  • 一、类名作为形参 1、表示可以传递本类对象的引用作为...1、使用抽象类作为形参意味着可以接受一个他的子类的对象的引用,即将子类的对象的引用作为参数传到方法中 2、可以传递null,但会报NullPointerException异常 
  • 1. 使参数可以双向传递,也就是形参的值改变会引起实参的值的改变。 这一功能在C++中已经可以用引用代替了,当然如果在C++中使用指针的这一功能也未尝不可。 2. 提高数据传递的效率,如果程序中要传递的数据很大...
  • 形参,方法头括号里的参数,也就是方法体中使用的部分 实参,给方法传入的参数 传值调用,基本数据类型作为参数,会产生值的副本,形参操作不影响实参 传引用调用,引用类型作为参数 类类型 接口 数组 传引用类型...
  • 有人学了继承,认为他是面向对象特点之一,就在所有能用到继承的地方使用继承,而不考虑究竟该不该使用,无疑,这是错误的。那么,究竟该如何使用继承呢?
  • 重写的方法形参必须相同

    千次阅读 2013-12-29 13:21:41
    子类重写父类的方法后可以实现多态,重写时形参必须和父类的形参相同。如果不同,那么就不算重写,对子类来说,该方法属于重载。如下面的equals方法: package bzq12_29; public class EqualsTest { public static...
  • 由于抽象类无法实例化,所以必须有继承抽象类的子类帮助建立对象 方法的形参是抽象类名,其实需要的是抽象类子类的对象 方法的返回值是抽象类名,其实返回的是抽象类子类的对象 3、接口名作为形参和返回值 和抽象...
  • 【JAVA基础】父类类型做形参

    千次阅读 2015-07-20 21:42:44
    父类类型的形参使用 为了方便,加入一个类有多个子类,将引用设为父类型,那么在用到多个子类的时候只需要用一个父类型的引用就够了。 汽车,我们知道汽车有多种多样。汽车有很多特征,比如颜色(carcolor),类型...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 64,422
精华内容 25,768
关键字:

形参怎么使用继承参数