精华内容
下载资源
问答
  • 面向对象的四个基本特征

    千次阅读 2015-10-03 09:36:54
    面向对象程序设计具有4共同特征:抽象性、封装性、继承性和多态性。 1.抽象 抽象是人们认识事物的常用方法,比如地图的绘制。抽象的过程就是如何简化、概括所观察到的现实世界,并为人们所用的过程。 ...

    面向对象程序设计具有4个共同特征:抽象性、封装性、继承性和多态性。

    1.抽象

    抽象是人们认识事物的常用方法,比如地图的绘制。抽象的过程就是如何简化、概括所观察到的现实世界,并为人们所用的过程。

    抽象是软件开发的基础。软件开发离不开现实环境,但需要对信息细节进行提炼、抽象,找到事物的本质和重要属性。

    抽象包括两个方面:过程抽象和数据抽象。过程抽象把一个系统按功能划分成若干个子系统,进行"自顶向下逐步求精"的程序设计。数据抽象以数据为中心,把数据类型和施加在该类型对象上的操作作为一个整体(对象)来进行描述,形成抽象数据类型ADT。

    所有编程语言的最终目的都是提供一种"抽象"方法。一种较有争议的说法是:解决问题的复杂程度直接取决于抽象的种类及质量。其中,"种类"是指准备对什么进行"抽象"。汇编语言是对基础机器的少量抽象。后来的许多"命令式"语言(如FORTRAN、BASIC和C)是对汇编语言的一种抽象。与汇编语言相比,这些语言已有了较大的进步,但它们的抽象原理依然要求程序设计者着重考虑计算机的结构,而非考虑问题本身的结构。在机器模型(位于"方案空间")与实际解决的问题模型(位于"问题空间")之间,程序员必须建立起一种联系。这个过程要求人们付出较大的精力,而且由于它脱离了编程语言本身的范围,造成程序代码很难编写,而且要花较大的代价进行维护。由此造成的副作用便是一门完善的"编程方法"学科。

    为机器建模的另一个方法是为要解决的问题制作模型。对一些早期语言来说,如LISP和APL,它们的做法是"从不同的角度观察世界"、"所有问题都归纳为列表"或"所有问题都归纳为算法"。PROLOG则将所有问题都归纳为决策链。对于这些语言,可以认为它们一部分是面向基于"强制"的编程,另一部分则是专为处理图形符号设计的。每种方法都有自己特殊的用途,适合解决某一类的问题。但只要超出了它们力所能及的范围,就会显得非常笨拙。

    面向对象的程序设计在此基础上则跨出了一大步,程序员可利用一些工具来表达问题空间内的元素。由于这种表达非常普遍,所以不必受限于特定类型的问题。人们将问题空间中的元素以及它们在方案空间的表示物称作"对象"。当然,还有一些在问题空间没有对应体的其他对象。通过添加新的对象类型,程序可进行灵活的调整,以便与特定的问题配合。所以在阅读方案的描述代码时,会读到对问题进行表达的话语。与以前的方法相比,这无疑是一种更加灵活、更加强大的语言抽象方法。

    总之,OOP允许人们根据问题,而不是根据方案来描述问题。然而,仍有一个联系途径回到计算机。每个对象都类似一台小计算机;它们有自己的状态,而且可要求它们进行特定的操作。与现实世界的"对象"或者"物体"相比,编程"对象"与它们也存在共通的地方:它们都有自己的特征行为

    2.封装

    封装是面向对象编程的特征之一,也是类和对象的主要特征。封装将数据以及加在这些数据上的操作组织在一起,成为有独立意义的构件。外部无法直接访问这些封装了的数据,从而保证了这些数据的正确性。如果这些数据发生了差错,也很容易定位错误是由哪个操作引起的。

    如果外部需要访问类里面的数据,就必须通过接口(Interface)进行访问。接口规定了可对一个特定的对象发出哪些请求。当然,必须在某个地方存在着一些代码,以便满足这些请求。这些代码与那些隐藏起来的数据叫作"隐藏的实现"。站在过程化程序编写(Procedural Programming)的角度,整个问题并不显得复杂。一种类型含有与每种可能的请求关联起来的函数。一旦向对象发出一个特定的请求,就会调用那个函数。通常将这个过程总结为向对象"发送一条消息"(提出一个请求)。对象的职责就是决定如何对这条消息作出反应(执行相应的代码)。

    若任何人都能使用一个类的所有成员,那么可对这个类做任何事情,则没有办法强制他们遵守任何约束--所有东西都会暴露无遗。

    有两方面的原因促使了类的编制者控制对成员的访问。第一个原因是防止程序员接触他们不该接触的东西--通常是内部数据类型的设计思想。若只是为了解决特定的问题,用户只需操作接口即可,无需明白这些信息。类向用户提供的实际是一种服务,因为他们很容易就可看出哪些对自己非常重要,以及哪些可忽略不计。进行访问控制的第二个原因是允许库设计人员修改内部结构,不用担心它会对客户程序员造成什么影响。例如,编制者最开始可能设计了一个形式简单的类,以便简化开发。以后又决定进行改写,使其更快地运行。若接口与实现方法早已隔离开,并分别受到保护,就可放心做到这一点,只要求用户重新链接一下即可。

    封装考虑的是内部实现,抽象考虑的是外部行为。符合模块化的原则,使得软件的可维护性、扩充性大为改观。

    3.继承

    继承是一种联结类的层次模型,并且允许和鼓励类的重用,它提供了一种明确表述共性的方法。对象的一个新类可以从现有的类中派生,这个过程称为类的继承。新类继承了原始类的特性,新类称为原始类的派生类(子类),而原始类称为新类的基类(父类)。派生类可以从它的基类那里继承方法和实例变量,并且派生类可以修改或增加新的方法使之更适合特殊的需求。这也体现了大自然中一般与特殊的关系。继承性很好地解决了软件的可重用性问题。比如说,所有的Windows应用程序都有一个窗口,它们可以看作都是从一个窗口类派生出来的。但是有的应用程序用于文字处理,有的应用程序用于绘图,这是由于派生出了不同的子类,各个子类添加了不同的特性。

    4.多态性

    多态性是指允许不同类的对象对同一消息作出响应。比如同样的加法,把两个时间加在一起和把两个整数加在一起肯定完全不同。又比如,同样的选择"编辑"、"粘贴"操作,在字处理程序和绘图程序中有不同的效果。多态性包括参数化多态性和运行时多态性。多态性语言具有灵活、抽象、行为共享、代码共享的优势,很好地解决了应用程序函数同名问题。

    最后,以Alan Kay的话作为本节的结束语。他总结了Smalltalk(这是第一种成功的面向对象程序设计语言,也是Java的基础语言)的五大基本特征。通过这些特征,读者可以理解"纯粹"的面向对象程序设计方法。

    (1)所有东西都是对象。可将对象想象成一种新型变量,它保存着数据,但可要求它对自身进行操作。理论上讲,可从要解决的问题上,提出所有概念性的组件,然后在程序中将其表达为一个对象。

    (2)程序是一大堆对象的组合。通过消息传递,各对象知道自己该做些什么。为了向对象发出请求,需向那个对象"发送一条消息"。更具体地讲,可将消息想象为一个调用请求,它调用的是从属于目标对象的一个子例程或函数。

    (3)每个对象都有自己的存储空间,可容纳其他对象。或者说,通过封装现有对象,可制作出新型对象。所以,尽管对象的概念非常简单,但在程序中却可达到任意高的复杂程度。

    (4)每个对象都有一种类型。根据语法,每个对象都是某个"类(Class)"的一个"实例"。其中,"类"是"类型(Type)"的同义词。一个类最重要的特征就是"能将什么消息发给它?"。

    (5)同一类所有对象都能接收相同的消息。这实际是别有含义的一种说法,读者不久便能理解。由于类型为"圆(Circle)"的一个对象也属于类型为"形状(Shape)"的一个对象,所以一个"圆"完全能接收"形状"的消息。这意味着可让程序代码统一指挥"形状",令其自动控制所有符合"形状"描述的对象,其中自然包括"圆"。这一特性称为对象的"可替换性",是OOP最重要的概念之一。


    展开全文
  •  【百度地图开发之】百度地图基本操作功能实现讲解(博客地址:http://blog.csdn.net/developer_jiangqq),转载请注明。  Author:hmjiangqq  Email:jiangqqlmj@163.com    上一篇我们学习了【百度地图开发之...
         写在前面的话:
    

      【百度地图开发之四】百度地图基本操作功能实现讲解(博客地址:http://blog.csdn.net/developer_jiangqq),转载请注明。

         Author:hmjiangqq

         Email:jiangqqlmj@163.com  

      上一篇我们学习了【百度地图开发之三】百度地图UI控制功能讲解(点击跳转),今天继续看一下百度地图一些基本的操作功能的实现;

    (一)基本介绍:

         百度地图的一些基本操作控制包括地图的缩放,旋转,俯视,单双击,长按等控制事件,实现前面的三个功能主要需要用到MapController类,单双击,长按事件需要用到MapView的监听事件处理接口MKMapTouchListener

    (二)控制类,接口基本介绍

         1:MapController:地图操作控制器,今天我们主要用到了其中的以下方法:

            ①:public float setZoom(float zoomLevel):设置地图的缩放级别,这个值的取值范围为[3,19];

            ②:public void setRotation(int rotate):设置地图的旋转角度

            ③:public void setOverlooking(int voidlook):设置地图的俯视角度

        2:MKMapTouchListener:地图点击事件监听器接口,主要有以下方法:

            ①:void onMapClick(GeoPoint point):地图单击事件,回调回来回来点击的地图的坐标点位置.

            ②:void onMapDoubleClick(GeoPoint point):地图双击事件,回调双击的地图的坐标点位置.

            ③:void onMapLongClick(GeoPoint point):地图的长按事件,回调长按的地图的坐标点位置.

    (三):事件监听器使用方法:

           我们只要在MapView对象中注册MKMapTouchListener监听器,并且实现其中的单击,双击,长按事件方法即可.具体实现方法如下:

    /**
             * 设置地图点击事件监听 
             */
            mapTouchListener = new MKMapTouchListener(){
    			@Override
    			public void onMapClick(GeoPoint point) {
    				touchType = "单击";
    				currentPt = point;
    				updateMapState();
    				
    			}
    
    			@Override
    			public void onMapDoubleClick(GeoPoint point) {
    				touchType = "双击";
    				currentPt = point;
    				updateMapState();
    			}
    
    			@Override
    			public void onMapLongClick(GeoPoint point) {
    				touchType = "长按";
    				currentPt = point;
    				updateMapState();
    			}
            };
            //给地图注册事件
            mMapView.regMapTouchListner(mapTouchListener);

    (四)下面我们来看下百度地图SDK中demo的例子(代码中的注释,在此基础上已经添加的很详细了)

         1:MyApplication.java:进行BMapManager全局变量的设置和密钥验证,代码如下: 

    package com.ztt.baidumap.ui;
    
    import android.app.Application;
    import android.content.Context;
    import android.util.Log;
    import android.widget.Toast;
    
    import com.baidu.mapapi.BMapManager;
    import com.baidu.mapapi.MKGeneralListener;
    import com.baidu.mapapi.map.MKEvent;
    /**
     * 自定义Application,进行key识别验证 (使用单例)
     * @author Jiangqq
     * @time 2014/03/15 10:14
     */
    public class MyApplication extends Application {
        public static MyApplication instance=null;
    	BMapManager mBMapManager = null;
    	public boolean m_bKeyRight = true;
        public static final String strKey = "vUAGbPwLpolIqiwWisnQPeIE";  //百度地图官网申请的密钥
    	public static MyApplication getInstance(){
    		return instance;
    	}
    	@Override
    	public void onCreate() {
    		super.onCreate();
    		instance=this;
    		//在APP应用启动的时候,进行初始化验证
    		initEngineManager(this);
    	}
    	
    	/**
    	 * 进行验证key
    	 * @param pContext
    	 */
    	private void initEngineManager(Context pContext)
    	{
    		 if (mBMapManager == null) {
    	            mBMapManager = new BMapManager(pContext);
    	        }
    
    	        if (!mBMapManager.init(strKey,new MyGeneralListener())) {
    	            Toast.makeText(MyApplication.getInstance(), 
    	                    "BMapManager  初始化错误!", Toast.LENGTH_LONG).show();
    	        }
    	}
    	// 常用事件监听,用来处理通常的网络错误,授权验证错误等
        static class MyGeneralListener implements MKGeneralListener {
            
            @Override
            public void onGetNetworkState(int iError) {
                if (iError == MKEvent.ERROR_NETWORK_CONNECT) {
                    Toast.makeText(MyApplication.getInstance(), "您的网络出错啦!",
                        Toast.LENGTH_LONG).show();
                }
                else if (iError == MKEvent.ERROR_NETWORK_DATA) {
                    Toast.makeText(MyApplication.getInstance(), "输入正确的检索条件!",
                            Toast.LENGTH_LONG).show();
                }else {
    				 Log.d("zttjiangqq", "iError="+iError);
    			}
                // ...
            }
    
            @Override
            public void onGetPermissionState(int iError) {
            	//非零值表示key验证未通过
                if (iError != 0) {
                    //授权Key错误:
                    Toast.makeText(MyApplication.getInstance(), 
                            "请在 DemoApplication.java文件输入正确的授权Key,并检查您的网络连接是否正常!error: "+iError, Toast.LENGTH_LONG).show();
                    MyApplication.getInstance().m_bKeyRight = false;
                }
                else{
                	MyApplication.getInstance().m_bKeyRight = true;
                	Toast.makeText(MyApplication.getInstance(), 
                            "key认证成功", Toast.LENGTH_LONG).show();
                }
            }
        }
    }
    
        2:布局文件:

    <?xml version="1.0" encoding="utf-8"?>
    
        
      <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent">
        
        <LinearLayout 
        android:orientation="horizontal"
        android:layout_width="fill_parent"
        android:layout_height="50dip">
        
        <Button
            android:id="@+id/zoombutton"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:background="@drawable/button_style"
            android:text="缩放" />
    
        <EditText
            android:id="@+id/zoomlevel"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="10" />
    
        <Button
            android:id="@+id/rotatebutton"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:background="@drawable/button_style"
            android:text="旋转" />
    
        <EditText
            android:id="@+id/rotateangle"
        	android:text="90"
        	android:layout_width="fill_parent"
        	android:layout_height="wrap_content"
        	android:layout_weight="1"
            />
    
        <Button
            android:id="@+id/overlookbutton"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
        	android:layout_weight="1"
            android:background="@drawable/button_style"
            android:text="俯视" />
    
        <EditText
            android:id="@+id/overlookangle"
        	android:text="-30"
        	android:layout_width="fill_parent"
        	android:layout_height="wrap_content"
        	android:layout_weight="1"
            />
        </LinearLayout>
        <TextView
            android:id="@+id/state"
        	android:text="点击、长按、双击地图以获取经纬度和地图状态"
        	android:layout_width="fill_parent"
        	android:layout_height="wrap_content"
        	android:lines="3"
            />
        <RelativeLayout 
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        >
      <com.baidu.mapapi.map.MapView android:id="@+id/bmapView"
    	    android:layout_width="fill_parent" android:layout_height="fill_parent" 
    	    android:clickable="true"     
    	/>
        <Button
            android:id="@+id/savescreen"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="true"
            android:layout_alignParentRight="true"
            android:layout_marginTop="10dip"
            android:background="@drawable/button_style"
            android:text="截图" />
    
    </RelativeLayout>
    
      </LinearLayout>
      
        3:功能实现Activity代码:

    package com.ztt.baidumap.ui;
    
    import java.io.File;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    
    import android.app.Activity;
    import android.graphics.Bitmap;
    import android.os.Bundle;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.TextView;
    import android.widget.Toast;
    
    import com.baidu.mapapi.BMapManager;
    import com.baidu.mapapi.map.MKMapTouchListener;
    import com.baidu.mapapi.map.MKMapViewListener;
    import com.baidu.mapapi.map.MapController;
    import com.baidu.mapapi.map.MapPoi;
    import com.baidu.mapapi.map.MapView;
    import com.baidu.platform.comapi.basestruct.GeoPoint;
    
    /**
     * 演示地图缩放,旋转,视角控制
     */
    public class MapControlDemo extends Activity {
    
    	/**
    	 *  MapView 是地图主控件
    	 */
    	private MapView mMapView = null;
    	/**
    	 *  用MapController完成地图控制 
    	 */
    	private MapController mMapController = null;
    	/**
    	 *  MKMapViewListener 用于处理地图事件回调
    	 */
    	MKMapViewListener mMapListener = null;
    	/**
    	 * 用于截获屏坐标
    	 */
    	MKMapTouchListener mapTouchListener = null; 
    	/**
    	 * 当前地点击点
    	 */
    	private GeoPoint currentPt = null; 
    	/**
    	 * 控制按钮
    	 */
    	private Button zoomButton = null;  //缩放
    	private Button rotateButton = null; //旋转
    	private Button overlookButton =null;  //俯视
    	private Button saveScreenButton = null;  //截图
    	/**
    	 * 
    	 */
    	private String touchType = null;
    	/**
    	 * 用于显示地图状态的面板
    	 */
    	private TextView mStateBar = null;
    	
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            /**
             * 使用地图sdk前需先初始化BMapManager.
             * BMapManager是全局的,可为多个MapView共用,它需要地图模块创建前创建,
             * 并在地图地图模块销毁后销毁,只要还有地图模块在使用,BMapManager就不应该销毁
             */
            MyApplication app = (MyApplication)this.getApplication();
            if (app.mBMapManager == null) {
                app.mBMapManager = new BMapManager(getApplicationContext());
                /**
                 * 如果BMapManager没有初始化则初始化BMapManager
                 */
                app.mBMapManager.init(MyApplication.strKey,new MyApplication.MyGeneralListener());
            }
            /**
              * 由于MapView在setContentView()中初始化,所以它需要在BMapManager初始化之后
              */
            setContentView(R.layout.activity_mapcontrol);
            mMapView = (MapView)findViewById(R.id.bmapView);
            /**
             * 获取地图控制器
             */
            mMapController = mMapView.getController();
            /**
             *  设置地图是否响应点击事件  .
             */
            mMapController.enableClick(true);
            /**
             * 设置地图缩放级别
             */
            mMapController.setZoom(12);
            
            mStateBar = (TextView) findViewById(R.id.state);
            /**
             * 初始化地图事件监听
             */
            initListener();
           
            /**
             * 将地图移动至天安门
             * 使用百度经纬度坐标,可以通过http://api.map.baidu.com/lbsapi/getpoint/index.html查询地理坐标
             * 如果需要在百度地图上显示使用其他坐标系统的位置,请发邮件至mapapi@baidu.com申请坐标转换接口
             */
            double cLat = 39.945 ;
            double cLon = 116.404 ;
            GeoPoint p = new GeoPoint((int)(cLat * 1E6), (int)(cLon * 1E6));
            mMapController.setCenter(p);
            
        }
        
        /**
         * 添加监听事件
         */
        private void initListener() {
        	/**
             * 设置地图点击事件监听 
             */
            mapTouchListener = new MKMapTouchListener(){
    			@Override
    			public void onMapClick(GeoPoint point) {
    				touchType = "单击";
    				currentPt = point;
    				updateMapState();
    				
    			}
    
    			@Override
    			public void onMapDoubleClick(GeoPoint point) {
    				touchType = "双击";
    				currentPt = point;
    				updateMapState();
    			}
    
    			@Override
    			public void onMapLongClick(GeoPoint point) {
    				touchType = "长按";
    				currentPt = point;
    				updateMapState();
    			}
            };
            //给地图注册事件
            mMapView.regMapTouchListner(mapTouchListener);
            /**
             * 设置地图事件监听
             */
            mMapListener = new MKMapViewListener() {
    			@Override
    			public void onMapMoveFinish() {
    				/**
    				 * 在此处理地图移动完成回调
    				 * 缩放,平移等操作完成后,此回调被触发
    				 */
    				updateMapState();
    			}
    			
    			@Override
    			public void onClickMapPoi(MapPoi mapPoiInfo) {
    				/**
    				 * 在此处理底图poi点击事件
    				 * 显示底图poi名称并移动至该点
    				 * 设置过: mMapController.enableClick(true); 时,此回调才能被触发
    				 * 
    				 */
    				
    			}
    
    			@Override
    			public void onGetCurrentMap(Bitmap b) {
    				/**
    				 *  当调用过 mMapView.getCurrentMap()后,此回调会被触发
    				 *  可在此保存截图至存储设备
    				 */
    				File file = new File("/mnt/sdcard/test.png");
                    FileOutputStream out;
                    try{
                        out = new FileOutputStream(file);
                        if(b.compress(Bitmap.CompressFormat.PNG, 70, out)) 
                        {
                            out.flush();
                            out.close();
                        }
                        Toast.makeText(MapControlDemo.this, 
                        	    "屏幕截图成功,图片存在: "+file.toString(),	
                        		 Toast.LENGTH_SHORT)
                             .show();
                    } 
                    catch (FileNotFoundException e) 
                    {
                        e.printStackTrace();
                    } 
                    catch (IOException e) 
                    {
                        e.printStackTrace(); 
                    }
                    
    			}
    
    			@Override
    			public void onMapAnimationFinish() {
    				/**
    				 *  地图完成带动画的操作(如: animationTo())后,此回调被触发
    				 */
    				updateMapState();
    			}
    
    			@Override
    			public void onMapLoadFinish() {
    				// TODO Auto-generated method stub
    				
    			}
    		};
    		mMapView.regMapViewListener(MyApplication.getInstance().mBMapManager, mMapListener);
    		/**
    		 * 设置按键监听
    		 */
    		zoomButton        = (Button)findViewById(R.id.zoombutton);
    		rotateButton      = (Button)findViewById(R.id.rotatebutton);
    		overlookButton    = (Button)findViewById(R.id.overlookbutton);
    		saveScreenButton  = (Button)findViewById(R.id.savescreen);
    		OnClickListener onClickListener = new OnClickListener(){
    			@Override
    			public void onClick(View view) {
    				if ( view.equals(zoomButton)){
    					perfomZoom();
    				}
    				else if( view.equals(rotateButton)){
    					perfomRotate();
    				}
    				else if( view.equals(overlookButton)){
    					perfomOverlook();
    				}
    				else if ( view.equals(saveScreenButton)){
    					//截图,在MKMapViewListener中保存图片
    				     mMapView.getCurrentMap();	
    				     Toast.makeText(MapControlDemo.this, 
    				    		 "正在截取屏幕图片...", 
    				    		 Toast.LENGTH_SHORT ).show();
    				          
    				}
    				updateMapState();
    			}
    			
    		};
    		zoomButton.setOnClickListener(onClickListener);
    		rotateButton.setOnClickListener(onClickListener);
    		overlookButton.setOnClickListener(onClickListener);
    		saveScreenButton.setOnClickListener(onClickListener);
        }
        /**
         * 处理缩放
         * sdk 缩放级别范围: [3.0,19.0]
         */
        private void perfomZoom(){
        	EditText  t  = (EditText) findViewById(R.id.zoomlevel);
        	try{
        	    float zoomLevel = Float.parseFloat(t.getText().toString());
        	    //设置地图缩放级别
        	    mMapController.setZoom(zoomLevel);
        	}catch(NumberFormatException e){
        		Toast.makeText(this, 
        	         "请输入正确的缩放级别", Toast.LENGTH_SHORT)
        		     .show();
        	}
        }
        /**
         * 处理旋转 
         * 旋转角范围: -180 ~ 180 , 单位:度   逆时针旋转  
         */
        private void perfomRotate(){
        	EditText  t  = (EditText) findViewById(R.id.rotateangle);
        	try{
        	    int rotateAngle = Integer.parseInt(t.getText().toString());
        	    //设置地图旋转角度
        	    mMapController.setRotation(rotateAngle);
        	}catch(NumberFormatException e){
        		Toast.makeText(this, 
        	         "请输入正确的旋转角度", Toast.LENGTH_SHORT)
        		     .show();
        	}
        }
        /**
         * 处理俯视
         * 俯角范围:  -45 ~ 0 , 单位: 度
         */
        private void perfomOverlook(){
        	EditText  t  = (EditText) findViewById(R.id.overlookangle);
        	try{
        	    int overlookAngle = Integer.parseInt(t.getText().toString());
        	    //设置地图的俯视
        	    mMapController.setOverlooking(overlookAngle);
        	}catch(NumberFormatException e){
        		Toast.makeText(this, 
        	         "请输入正确的俯角", Toast.LENGTH_SHORT)
        		     .show();
        	}	
        }
        
        /**
         * 更新地图状态显示面板
         */
        private void updateMapState(){
        	   if ( mStateBar == null){
        		   return ;
        	   }
        		String state  = "";
        		if ( currentPt == null ){
        			state = "点击、长按、双击地图以获取经纬度和地图状态";
        		}
        		else{
        			state = String.format(touchType+",当前经度 : %f 当前纬度:%f",currentPt.getLongitudeE6()*1E-6,currentPt.getLatitudeE6()*1E-6);
        		}
        		state += "\n";
        		state += String.format("zoom level= %.1f    rotate angle= %d   overlaylook angle=  %d",
                    mMapView.getZoomLevel(), 
                    mMapView.getMapRotation(),
                    mMapView.getMapOverlooking() 
        	    );
        		mStateBar.setText(state);
        }
        
        @Override
        protected void onPause() {
        	/**
        	 *  MapView的生命周期与Activity同步,当activity挂起时需调用MapView.onPause()
        	 */
            mMapView.onPause();
            super.onPause();
        }
        
        @Override
        protected void onResume() {
        	/**
        	 *  MapView的生命周期与Activity同步,当activity恢复时需调用MapView.onResume()
        	 */
            mMapView.onResume();
            super.onResume();
        }
        
        @Override
        protected void onDestroy() {
        	/**
        	 *  MapView的生命周期与Activity同步,当activity销毁时需调用MapView.destroy()
        	 */
            mMapView.destroy();
            super.onDestroy();
        }
        
        @Override
        protected void onSaveInstanceState(Bundle outState) {
        	super.onSaveInstanceState(outState);
        	mMapView.onSaveInstanceState(outState);
        	
        }
        
        @Override
        protected void onRestoreInstanceState(Bundle savedInstanceState) {
        	super.onRestoreInstanceState(savedInstanceState);
        	mMapView.onRestoreInstanceState(savedInstanceState);
        }
        
    }
    
      4:运行截图:



    [注明]AndroidManifest.xml的配置和之前的文章中一样.

    展开全文
  • 节 实现地图基本操作

    千次阅读 2016-10-12 09:21:01
    一、 创建我们的第一程序 首先我们先找到我们的Vs2013,启动它。 启动完成后的显示的画面如下: 下面我们新建一Silverlight项目,命名为HelloWord。创建方法如下:文件-新建-项目。在弹出的“新建项目”...

    一、 创建我们的第一个程序
    首先我们先找到我们的Vs2013,启动它。
    这里写图片描述
    启动完成后的显示的画面如下:
    这里写图片描述
    下面我们新建一个Silverlight项目,命名为HelloWord。创建方法如下:文件-新建-项目。在弹出的“新建项目”对话框中,按照下图所示,在模板中选择Silverlight,DotNet Framework 版本选择4.0,修改项目名称为“HelloWord”,点击确定。
    这里写图片描述
    在弹出的“新建Silverlight应用程序”对话框中选择Silverlight版本,我们默认选择Silverlight 5。
    这里写图片描述
    点击确定,这样我们的第一个Silverlight程序就创建完成了。
    这里写图片描述
    二、 地图加载
    1. 简单地图加载
    我们在工具箱里拖一个Map控件到当前页面。
    这里写图片描述
    在属性面板里设置属性如下图。
    这里写图片描述
    按照上面的属性设置后,整个map将充满整个页面,如下
    这里写图片描述
    这样我们就完成了一个简单的地图加载。可能有朋友会问,我们并没有设施地图源啊,其实,控件自动设置了一个默认的地图源,我们在地图控件上看到的地图就是这个默认地图源上的数据,我们可以通过map的layers字段设置我们自己想要的地图源。下面这段代码的作用就是设置默认地图源。

    <esri:Map Background="White" Margin="0" WrapAround="True">
                <esri:ArcGISTiledMapServiceLayer Url="http://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer"/>
    </esri:Map>
    

    Url的值就是地图服务的地址,
    http://services.arcgisonline.com/ArcGIS/rest/services这个地址上有很多免费的地图服务,大家可以访问看看。里面有影像地图服务和地形图等服务。下图我访问的结果。
    这里写图片描述
    我们现在看一下我们地图加载的效果,点击一下运行图标,可以在浏览器总运行我们的程序。
    这里写图片描述
    运行效果如下:
    这里写图片描述
    2. 地图类型
    (1) ArcGISTiledMapService
    ArcGISTiledMapService是一种地图服务类型,叫做瓦片地图服务,ArcGISTiledMapServiceLayer就是承载这种类型地图服务的控件。什么叫做瓦片地图呢,我们看网上的解释:
    瓦片地图金字塔模型是一种多分辨率层次模型,从瓦片金字塔的底层到顶层,分辨率越来越低,但表示的地理范围不变。——百度百科
    这里写图片描述
    首先确定地图服务平台所要提供的缩放级别的数量N,把缩放级别最低、地图比例尺最大的地图图片作为金字塔的底层,即第0层,并对其进行分块,从地图图片的左上角开始,从左至右、从上到下进行切割,分割成相同大小(比如256x256像素)的正方形地图瓦片,形成第0层瓦片矩阵;在第0层地图图片的基础上,按每2x2像素合成为一个像素的方法生成第1层地图图片,并对其进行分块,分割成与下一层相同大小的正方形地图瓦片,形成第1层瓦片矩阵;采用同样的方法生成第2层瓦片矩阵;…;如此下去,直到第N一1层,构成整个瓦片金字塔。——百度百科
    瓦片服务优点是:缓存效率高,加载快,可以渐进加载,坐标寻址简单。
    瓦片服务的缺点是:需要提前制作,耗时,产生文件巨大,占用存储大,一旦地图发生改变需要重新制作切片。
    (2) ArcGISDynamicMapService
    顾名思义ArcGISDynamicMapService,是动态地图服务,当我们访问一个地图范围的时候,地图服务器为根据我们的请求去动态的生成图片。
    动态地图服务的优点是:快速发布,地图修改后能快速发布服务。
    动态地图服务的缺点是:访问速度不如瓦片服务,服务器计算压力大,网络压力大。
    三、 地图移动缩放实现
    其实简单地图拖动缩放Map控件默认已经实现了,这里我们实现一下稍稍有点难度的需求。
    第一个需求,我们要地图默认显示山东省的位置。
    要实现这个需求,我们需要了解两个概念地理坐标系、投影坐标系、坐标系转换,对于非地理信息专业的朋友们这几个概念可能比较难懂,这里我们不去追求它的定义和推导,我们用通俗易懂方式来解释一下:
    凡是以经纬度为单位的都是地理坐标系,因为它归根结底是一个椭球体,只不过各个国家为了反映该国家所在区域地球的真实形状,而采用不同的数学模型对本不是椭球体的地球进行椭球体化。
    而投影坐标系,是对地理坐标系按照某种方式投影到平面上的,所以可以认为它是一个平面坐标系,单位自然是米或千米。
    关于投影算法我们比较常用有墨卡托投影和高斯(克吕格)投影。
    墨卡托(Mercator)投影,是一种”等角正切圆柱投影”,荷兰地图学家墨卡托(Gerhardus Mercator 1512-1594)在1569年拟定,假设地球被围在一中空的圆柱里,其标准纬线与圆柱相切接触,然后再假想地球中心有一盏灯,把球面上的图形投影到圆柱体上,再把圆柱体展开,这就是一幅选定标准纬线上的“墨卡托投影”绘制出的地图。墨卡托投影没有角度变形,由每一点向各方向的长度比相等,它的经纬线都是平行直线,且相交成直角,经线间隔相等,纬线间隔从标准纬线向两极逐渐增大。墨卡托投影的地图上长度和面积变形明显,但标准纬线无变形,从标准纬线向两极变形逐渐增大,但因为它具有各个方向均等扩大的特性,保持了方向和相互位置关系的正确。在地图上保持方向和角度的正确是墨卡托投影的优点,墨卡托投影地图常用作航海图和航空图,如果循着墨卡托投影图上两点间的直线航行,方向不变可以一直到达目的地,因此它对船舰在航行中定位、确定航向都具有有利条件,给航海者带来很大方便。“海底地形图编绘规范”(GB/T 17834-1999,海军航保部起草)中规定1:25万及更小比例尺的海图采用墨卡托投影,其中基本比例尺海底地形图(1:5万,1:25万,1:100万)采用统一基准纬线30°,非基本比例尺图以制图区域中纬为基准纬线。基准纬线取至整度或整分。
    这里写图片描述
    墨卡托投影坐标系取零子午线或自定义原点经线(L0)与赤道交点的投影为原点,零子午线或自定义原点经线的投影为纵坐标X轴,赤道的投影为横坐标Y轴,构成墨卡托平面直角坐标系。
    高斯-克吕格(Gauss-Kruger)投影简称“高斯投影”,又名”等角横切椭圆柱投影”,地球椭球面和平面间正形投影的一种。德国数学家、物理学家、天文学家高斯(Carl FriedrichGauss,1777一 1855)于十九世纪二十年代拟定,后经德国大地测量学家克吕格(Johannes Kruger,1857~1928)于 1912年对投影公式加以补充,故名。
    这里写图片描述
    该投影按照投影带中央子午线投影为直线且长度不变和赤道投影为直线的条件,确定函数的形式,从而得到高斯一克吕格投影公式。投影后,除中央子午线和赤道为直线外, 其他子午线均为对称于中央子午线的曲线。设想用一个椭圆柱横切于椭球面上投影带的中央子午线,按上述投影条件,将中央子午线两侧一定经差范围内的椭球面正形投影于椭圆柱面。将椭圆柱面沿过南北极的母线剪开展平,即为高斯投影平面。取中央子午线与赤道交点的投影为原点,中央子午线的投影为纵坐标x轴,赤道的投影为横坐标y轴,构成高斯克吕格平面直角坐标系。
    高斯-克吕格投影在长度和面积上变形很小,中央经线无变形,自中央经线向投影带边缘,变形逐渐增加,变形最大之处在投影带内赤道的两端。由于其投影精度高,变形小,而且计算简便(各投影带坐标一致,只要算出一个带的数据,其他各带都能应用),因此在大比例尺地形图中应用,可以满足军事上各种需要,能在图上进行精确的量测计算。
    按一定经差将地球椭球面划分成若干投影带,这是高斯投影中限制长度变形的最有效方法。分带时既要控制长度变形使其不大于测图误差,又要使带数不致过多以减少换带计算工作,据此原则将地球椭球面沿子午线划分成经差相等的瓜瓣形地带,以便分带投影。通常按经差6度或3度分为六度带或三度带。六度带自0度子午线起每隔经差6度自西向东分带,带号依次编为第 1、2…60带。三度带是在六度带的基础上分成的,它的中央子午线与六度带的中央子午线和分带子午线重合,即自 1.5度子午线起每隔经差3度自西向东分带,带号依次编为三度带第 1、2…120带。我国的经度范围西起 73°东至135°,可分成六度带十一个,各带中央经线依次为75°、81°、87°、……、117°、123°、129°、135°,或三度带二十二个。六度带可用于中小比例尺(如 1:250000 )测图,三度带可用于大比例尺(如 1:10000)测图,城建坐标多采用三度带的高斯投影。
    高斯- 克吕格投影是按分带方法各自进行投影,故各带坐标成独立系统。以中央经线投影为纵轴(x), 赤道投影为横轴(y),两轴交点即为各带的坐标原点。纵坐标以赤道为零起算,赤道以北为正,以南为负。我国位于北半球,纵坐标均为正值。横坐标如以中央经线为零起算,中央经线以东为正,以西为负,横坐标出现负值,使用不便,故规定将坐标纵轴西移500公里当作起始轴,凡是带内的横坐标值均加 500公里。由于高斯-克吕格投影每一个投影带的坐标都是对本带坐标原点的相对值,所以各带的坐标完全相同,为了区别某一坐标系统属于哪一带,在横轴坐标前加上带号,如(4231898m,21655933m),其中21即为带号。例如我过常用的北京54坐标系就是如此。
    我们在做开发的时候,尤其是web地图开发,两种坐标系至关重要4326 GCS_WGS_1984 和 102100 WGS_1984_web_mercator_auxiliary_sphere 。
    4326 GCS_WGS_1984 是WGS1984,属于地理坐标系,相信大家对它都有所耳闻,他就是大名鼎鼎的gps采用的坐标系,也就是通过gps拿到的坐标信息都是按这个坐标系给我们的经度和纬度。当然,如果你是做移动平台上的gps,获得的经纬度也是按这个坐标系。
    102100 WGS_1984_web_mercator_auxiliary_sphere则是目前在线地图采用的通用坐标系,属于投影坐标系。
    如果我们采用googlemap做底图,然后想通过gps将位置在地图上显示,不经过任何转换直接在googlemap上显示是不行的,因为他们的坐标系不统一。所以在显示之前就必须将gps获取点进行坐标转换到WGS_1984_web_mercator,然后在googlemap上显示。
    下面接着实现我们的需求,首先我们得了解我们使用的地图服务采用的什么坐标系,怎么看呢?把地图服务的Url复制到浏览器中打开,浏览器中会显示该服务一些信息,我们看Tile Info下的信息

    这里写图片描述
    Height、Width两个属性表示当前服务的瓦片大小是256*256px,当前服务的金字塔模型是24层。下面是24个层瓦片的信息。
    这里写图片描述
    Spatial Reference:102100代表当前服务使用的坐标系是102100 WGS_1984_web_mercator_auxiliary_sphere坐标系。
    我们现在知道了地图服务的坐标系,要显示山东省的范围,我们就得需要知道山东省的坐标范围,我在网上搜索了一下,结果是:东经114度19分 - 122度43分 纬度:北纬34度22分 - 38度23分。我们用一个矩形表示一下
    这里写图片描述
    将上述坐标转换成度分别为114.3166666666666667-122.7166666666666667,34.3666666666666667-38.3833333333333333。
    要实现默认显示位置,我们需要用到Map控件的Extent(Envelope)属性,Envelope构造函数需要四个参数分别是(x min,y min,x max,y max)。那么山东省的范围可以表示为:Envelope(114.3166666666666667,34.3666666666666667,122.7166666666666667,38.3833333333333333),我们现在使用的地理坐标,而地图服务使用的墨卡托投影坐标,所以我们还需要把经纬度转换成平面坐标,具体我们将在代码中实现。
    我们在map控件上添加Map_loaded事件处理函数,添加方法如下(其实有很多方法,大家自行百度):在前台代码中的map控件处添加Loaded=“Map_loaded”和Name=“map”。
    这里写图片描述
    具体事件处理函数如下:
    这里写图片描述
    首先我们定义了四个double型的数字,分别代表最小X、最小y,最大x、最大y。用这四个数字构造两个点,分别代表最左下方的点C和最右上方点D,把这两个点转换成Mector投影坐标后构造一个Envelope,设置当前地图的Extent为我们构造的Envelope,这样我们的需求就实现了。
    经纬度转墨卡托算法实现:
    这里写图片描述
    墨卡托转经纬实现:
    这里写图片描述
    运行一下我们的程序,如果没有错误的话,应该显示如下画面,默认的显示在山东省的范围。
    这里写图片描述
    其实,实现这个需求的方法不止这一种,感兴趣的朋友自己研究一下。
    四、 比例尺显示
    比例尺空api中已经有现成的,我们直接用即可,使用方法,从工具箱拖一个ScaleLine控件到当前地图,设置器布局属性如下:
    这里写图片描述
    我们可以通过设置MapUnit属性调整比例尺显示单位。
    这里写图片描述
    在后台代码中添加如下代码,设置比例尺关联的map控件。
    这里写图片描述
    OK,就这样简单,运行即可。
    这里写图片描述
    五、 鼠标坐标拾取
    这里我们的需求是,捕捉鼠标的坐标,动态的显示在地图的右下角。
    首先我们在地图的右下方添加一个label控件,用来展示当前鼠标的坐标值,name=Lable_XY。设置其属性如下:
    这里写图片描述
    设置字体颜色为红色,具体代码如下

     <esri:Map Background="White" Margin="0" WrapAround="True" Loaded="Map_Loaded" x:Name="map">
                <esri:ArcGISDynamicMapServiceLayer Url="http://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer"/>
            </esri:Map>
            <esri:ScaleLine HorizontalAlignment="Left" Margin="0" VerticalAlignment="Bottom"  x:Name="ScaleLine1" MapUnit="Kilometers"/>
            <sdk:Label HorizontalAlignment="Right" Margin="0" VerticalAlignment="Bottom" FontSize="12" Foreground="Red"/>
        </Grid>
    我们给map控件添加鼠标移动事件处理方法,前台代码如下
    <Grid x:Name="LayoutRoot" Background="White">
            <esri:Map Background="White" Margin="0" WrapAround="True" Loaded="Map_Loaded" x:Name="map" MouseMove="map_MouseMove">
                <esri:ArcGISDynamicMapServiceLayer Url="http://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer"/>
            </esri:Map>
            <esri:ScaleLine HorizontalAlignment="Left" Margin="0" VerticalAlignment="Bottom"  x:Name="ScaleLine1" MapUnit="Kilometers"/>
            <sdk:Label HorizontalAlignment="Right" Margin="0" VerticalAlignment="Bottom" FontSize="12" Foreground="Red" Name="label_xy"/>
    </Grid>
    

    后台事件处理方法如下:

    private void map_MouseMove(object sender, MouseEventArgs e)
            {
                System.Windows.Point screenP = e.GetPosition(map);
                ESRI.ArcGIS.Client.Geometry.MapPoint mp = map.ScreenToMap(screenP);
                MapPoint mp1 = Mercator2lonLat(new MapPoint(mp.X, mp.Y));
                 string local_LON = jiaoduTodufenmiao(mp1.X);
                 string local_LAT = jiaoduTodufenmiao(mp1.Y);
                label_xy.Content = local_LON + "  " + local_LAT;
            }
    

    jiaoduTodufenmiao是一个自定义的方法,作用是将十进制度转换成度分秒字符串。

     public  string jiaoduTodufenmiao(double x)
            {
                string xStr = string.Empty;
                double degree = Math.Floor(x);// Math.Truncate(x);
                double tempDb = (x - degree) * 60;
                double minute = Math.Floor(tempDb);// Math.Truncate(tempDb);
                double second = (tempDb - minute) * 60;
                second = Math.Round(second, 4);
                string strMinute = minute.ToString();
                if (strMinute.Length == 1)
                {
                    strMinute = string.Format("0{0}", strMinute);
                }
                string strSecond = second.ToString();
                int dotIndex = strSecond.IndexOf('.');
                if (dotIndex != -1)
                {
                    string sub1 = strSecond.Substring(0, dotIndex);
                    string sub2 = strSecond.Substring(dotIndex + 1);
                    if (sub1.Length == 1)
                        sub1 = string.Format("0{0}", sub1);
                    int sub2Len = sub2.Length;
                    if (sub2Len < 4)
                    {
                        for (int i = 0; i < 4 - sub2Len; i++)
                            sub2 = string.Format("{0}0", sub2);
                    }
                    strSecond = string.Format("{0}", Math.Round(double.Parse(sub1), 0));
                }
                // 度分秒
                xStr = string.Format("{0}°{1}′{2}″", degree.ToString(), strMinute, strSecond);
                return xStr;
            }

    我们运行一下程序,结果如下。

    这里写图片描述

    展开全文
  • 面向对象的4个基本特征

    千次阅读 2010-11-03 10:17:00
    面向对象的4个基本特征 在上述面向对象的基本概念基础之上,不可避免地要涉及到面向对象程序设计所具有的4个共同特征:抽象性、封装性、继承性和多态性。 1.抽象 抽象是人们认识事物的常用方法,比如地图的绘制。...

    上个周末霸笔大唐移动的应用程序软件工程师试题,有一道面向对象的4个特征,以前都是接触的三个,怎么多出了一个?原来就是抽象性。。。

    面向对象的4个基本特征
    在上述面向对象的基本概念基础之上,不可避免地要涉及到面向对象程序设计所具有的4个共同特征:抽象性、封装性、继承性和多态性。
    1.抽象
    抽象是人们认识事物的常用方法,比如地图的绘制。抽象的过程就是如何简化、概括所观察到的现实世界,并为人们所用的过程。
    抽象是软件开发的基础。软件开发离不开现实环境,但需要对信息细节进行提炼、抽象,找到事物的本质和重要属性。
    抽象包括两个方面:过程抽象和数据抽象。过程抽象把一个系统按功能划分成若干个子系统,进行"自顶向下逐步求精"的程序设计。数据抽象以数据为中心,把数据类型和施加在该类型对象上的操作作为一个整体(对象)来进行描述,形成抽象数据类型ADT。
    所有编程语言的最终目的都是提供一种"抽象"方法。一种较有争议的说法是:解决问题的复杂程度直接取决于抽象的种类及质量。其中,"种类"是指准备对什么进行"抽象"。汇编语言是对基础机器的少量抽象。后来的许多"命令式"语言(如FORTRAN、BASIC和C)是对汇编语言的一种抽象。与汇编语言相比,这些语言已有了较大的进步,但它们的抽象原理依然要求程序设计者着重考虑计算机的结构,而非考虑问题本身的结构。在机器模型(位于"方案空间")与实际解决的问题模型(位于"问题空间")之间,程序员必须建立起一种联系。这个过程要求人们付出较大的精力,而且由于它脱离了编程语言本身的范围,造成程序代码很难编写,而且要花较大的代价进行维护。由此造成的副作用便是一门完善的"编程方法"学科。
    为机器建模的另一个方法是为要解决的问题制作模型。对一些早期语言来说,如LISP和APL,它们的做法是"从不同的角度观察世界"、"所有问题都归纳为列表"或"所有问题都归纳为算法"。PROLOG则将所有问题都归纳为决策链。对于这些语言,可以认为它们一部分是面向基于"强制"的编程,另一部分则是专为处理图形符号设计的。每种方法都有自己特殊的用途,适合解决某一类的问题。但只要超出了它们力所能及的范围,就会显得非常笨拙。
    面向对象的程序设计在此基础上则跨出了一大步,程序员可利用一些工具来表达问题空间内的元素。由于这种表达非常普遍,所以不必受限于特定类型的问题。人们将问题空间中的元素以及它们在方案空间的表示物称作"对象"。当然,还有一些在问题空间没有对应体的其他对象。通过添加新的对象类型,程序可进行灵活的调整,以便与特定的问题配合。所以在阅读方案的描述代码时,会读到对问题进行表达的话语。与以前的方法相比,这无疑是一种更加灵活、更加强大的语言抽象方法。
    总之,OOP允许人们根据问题,而不是根据方案来描述问题。然而,仍有一个联系途径回到计算机。每个对象都类似一台小计算机;它们有自己的状态,而且可要求它们进行特定的操作。与现实世界的"对象"或者"物体"相比,编程"对象"与它们也存在共通的地方:它们都有自己的特征和行为。
    2.封装
    封装是面向对象编程的特征之一,也是类和对象的主要特征。封装将数据以及加在这些数据上的操作组织在一起,成为有独立意义的构件。外部无法直接访问这些封装了的数据,从而保证了这些数据的正确性。如果这些数据发生了差错,也很容易定位错误是由哪个操作引起的。
    如果外部需要访问类里面的数据,就必须通过接口(Interface)进行访问。接口规定了可对一个特定的对象发出哪些请求。当然,必须在某个地方存在着一些代码,以便满足这些请求。这些代码与那些隐藏起来的数据叫作"隐藏的实现"。站在过程化程序编写(Procedural Programming)的角度,整个问题并不显得复杂。一种类型含有与每种可能的请求关联起来的函数。一旦向对象发出一个特定的请求,就会调用那个函数。通常将这个过程总结为向对象"发送一条消息"(提出一个请求)。对象的职责就是决定如何对这条消息作出反应(执行相应的代码)。
    若任何人都能使用一个类的所有成员,那么可对这个类做任何事情,则没有办法强制他们遵守任何约束--所有东西都会暴露无遗。
    有两方面的原因促使了类的编制者控制对成员的访问。第一个原因是防止程序员接触他们不该接触的东西--通常是内部数据类型的设计思想。若只是为了解决特定的问题,用户只需操作接口即可,无需明白这些信息。类向用户提供的实际是一种服务,因为他们很容易就可看出哪些对自己非常重要,以及哪些可忽略不计。进行访问控制的第二个原因是允许库设计人员修改内部结构,不用担心它会对客户程序员造成什么影响。例如,编制者最开始可能设计了一个形式简单的类,以便简化开发。以后又决定进行改写,使其更快地运行。若接口与实现方法早已隔离开,并分别受到保护,就可放心做到这一点,只要求用户重新链接一下即可。
    封装考虑的是内部实现,抽象考虑的是外部行为。符合模块化的原则,使得软件的可维护性、扩充性大为改观。
    3.继承
    继承是一种联结类的层次模型,并且允许和鼓励类的重用,它提供了一种明确表述共性的方法。对象的一个新类可以从现有的类中派生,这个过程称为类的继承。新类继承了原始类的特性,新类称为原始类的派生类(子类),而原始类称为新类的基类(父类)。派生类可以从它的基类那里继承方法和实例变量,并且派生类可以修改或增加新的方法使之更适合特殊的需求。这也体现了大自然中一般与特殊的关系。继承性很好地解决了软件的可重用性问题。比如说,所有的Windows应用程序都有一个窗口,它们可以看作都是从一个窗口类派生出来的。但是有的应用程序用于文字处理,有的应用程序用于绘图,这是由于派生出了不同的子类,各个子类添加了不同的特性。
    关于继承的详细讨论,将在第4.1~4.2节进行。
    4.多态性
    多态性是指允许不同类的对象对同一消息作出响应。比如同样的加法,把两个时间加在一起和把两个整数加在一起肯定完全不同。又比如,同样的选择"编辑"、"粘贴"操作,在字处理程序和绘图程序中有不同的效果。多态性包括参数化多态性和运行时多态性。多态性语言具有灵活、抽象、行为共享、代码共享的优势,很好地解决了应用程序函数同名问题。
    关于多态性的讨论,将在4.7~4.9节进行。
    最后,以Alan Kay的话作为本节的结束语。他总结了Smalltalk(这是第一种成功的面向对象程序设计语言,也是Java的基础语言)的五大基本特征。通过这些特征,读者可以理解"纯粹"的面向对象程序设计方法。
    (1)所有东西都是对象。可将对象想象成一种新型变量,它保存着数据,但可要求它对自身进行操作。理论上讲,可从要解决的问题上,提出所有概念性的组件,然后在程序中将其表达为一个对象。
    (2)程序是一大堆对象的组合。通过消息传递,各对象知道自己该做些什么。为了向对象发出请求,需向那个对象"发送一条消息"。更具体地讲,可将消息想象为一个调用请求,它调用的是从属于目标对象的一个子例程或函数。
    (3)每个对象都有自己的存储空间,可容纳其他对象。或者说,通过封装现有对象,可制作出新型对象。所以,尽管对象的概念非常简单,但在程序中却可达到任意高的复杂程度。
    (4)每个对象都有一种类型。根据语法,每个对象都是某个"类(Class)"的一个"实例"。其中,"类"是"类型(Type)"的同义词。一个类最重要的特征就是"能将什么消息发给它?"。
    (5)同一类所有对象都能接收相同的消息。这实际是别有含义的一种说法,读者不久便能理解。由于类型为"圆(Circle)"的一个对象也属于类型为"形状(Shape)"的一个对象,所以一个"圆"完全能接收"形状"的消息。这意味着可让程序代码统一指挥"形状",令其自动控制所有符合"形状"描述的对象,其中自然包括"圆"。这一特性称为对象的"可替换性",是OOP最重要的概念之一。

    展开全文
  • 百度地图 Android SDK是一套基于Android 2.1及以上版本设备的应用程序接口, 可以通过该接口实现丰富的LBS功能。练习使用了一下百度地图sdk,感觉还不错。 第一步:将百度地图的jar包和.so文件拷入到libs文件夹中。 ...
  • 今天,想给大家带来一基于百度地图官方开放的API开发的高仿百度地图的Demo(还称不上是一APP),基本实现了百度地图的几大核心功能,百度地图中的基本地图,百度地图的定位,百度地图的全景显示,百度地图的导航等...
  • 地图四色原理

    万次阅读 2017-07-12 10:18:04
    ... 地图只使用种颜色,是因为四色定理的存在。四色定理是一著名的数学定理,通俗的说法是:每平面地图都可以只用种颜色来染色,而且没有两邻接的区
  • 今天,想给大家带来一基于百度地图官方开放的API开发的高仿百度地图的Demo(还称不上是一APP),基本实现了百度地图的几大核心功能,百度地图中的基本地图,百度地图的定位,百度地图的全景显示,百度地图的导航等...
  • iOS百度地图SDK基本配置和使用

    千次阅读 2015-08-13 19:20:26
    介绍:在iOS的开发中,有些应用需要实现与地图相关功能,这时候可以选择使用苹果自带的框架进行实现,也可以选择使用百度所提供的这第三方SDK进行功能的实现,下面将对百度地图的SDK的基本使用进行说明: ...
  • 百度地图API使用系列4-基本地图2

    千次阅读 2015-09-29 18:02:56
    继续为大家带来 百度地图API 系列博文 这篇博文主要介绍一下 ...基本地图1 好了下面开始我们本篇博文之旅 首先介绍百度地图支持显示的几何图形 1.点(Dot) 2.折线(Polyline) 3.弧线(Arc) 4.圆(Circl
  • 这是一最简单的地图demo。 public class BaseMapDemo extends Activity { final static String TAG = "MainActivity"; /** * MapView 是地图主控件 */ private MapView mMapView = null; /**
  • 地图四色着图的C语言实现

    千次阅读 2014-11-09 15:24:34
    四色定理是一著名的数学定理,通俗的说法是:每平面地图都可以只用种颜色来染色,而且没有两邻接的区域颜色相同。1976年借助电子计算机证明了四色问题,问题也终于成为定理,这是第一借助计算机证明的定理...
  • 地图显示分为MapView和 AMap 两类 MapView重写activity内的基本所有生命周期方法 Amap由mapview产生:aMap = mapView.getMap(); 其实amap才是真正操纵地图显示的类 amap的设置方法: /** * 设置一些amap的属性...
  • 写在前面的话:  【百度地图开发之五】百度地图地位图层基本使用方法讲解(博客地址:http://blog.csdn.net/developer_jiangqq... 上一篇我们学习了【百度地图开发之】百度地图基本操作功能实现讲解(),今天继续看一下
  • 今天,我们接着上一讲,上一讲我们把地图上界面自定义了一番,加上了按钮等一系列的控件,但是还没有给这些加上具体的功能,今天这一讲,主要是实现几种地图的切换,是否开启实时交通,通过自定义的按钮去控制地图的...
  • Android 百度地图 SDK v3.0.0 () 引入离线地图功能

    万次阅读 多人点赞 2014-07-14 13:20:57
    一直觉得地图应用支持离线地图很重要啊,我等移动2G屌丝,流量不易,且用且珍惜。 对于官方开发指南对于离线地图的教程,提供了两种方案: 第一,手动导入,先将从官网下载的离线包解压,把vmp文件夹拷入SD卡根目录...
  • 高德地图自定义图形绘制中坐标转换的问题,绘制高级自定义图形1. 绘制正方形图1图2图3利用高德地图绘制任意旋转角度的椭圆效果图如上图1图4图5 ...* 生成一个长方形的四个坐标点 */ private List<LatLng> ...
  • HTML5 / JS实现百度地图基本常用功能

    千次阅读 2016-11-21 20:09:41
    很多网站都会使用到地图功能,提供地图接口的第三方也有不少,我这里来聊一下百度地图提供的API及百度地图基本功能的实现
  • 2007年第2周最热网友收藏 C#的四个基本技巧(97),共105人收藏,yanglilibaobao首先收藏 我来做个好人吧,40种网站设计常用技巧(97),共377人收藏,wuzeng2002首先收藏 Visual C#常用函数和方法集汇总(85),共93人...
  • 今天,我就接着来浅谈一下关于百度地图的内景... 实现街景展示的地点的搜索,需要涉及到几方面的知识:HttpClient网络请求封装,解析JSON数据,封装解析后JSON数据。其实展示内景或者外景很简单,只需要获取到内景的u
  • 二、openlayer中map基本框架   三、加载天地图   、总结     一、引言   换工作中间耽误了好长时间没有更过blog了,现在终于有时间搞开源webgis了,先从openlayer下手,后面打算在研究geoserver、...
  • 百度地图总结第篇之路线规划功能

    万次阅读 热门讨论 2016-03-05 20:11:19
    百度地图路线规划 1、公交路线规划 2、驾车路线规划 3、骑行路线规划 4、步行路线规划
  • 我们就实现了在天地图上显示坐标轨迹。可以根据后台查询出来的数据在地图上显示轨迹。
  • 最近年前的项目已经上线,于是在空闲的时间就研究了百度地图的SDK,当前的版本:Android SDK v3.3.0 。 虽然百度地图网上相关代码比较多,大多可能都是比较旧的版本,且百度地图API的改动感觉也比较大,所以再此跟...
  • 众所周知,地球是椭球的(当然,我们...这坐标系,就产生了我们常说的经纬度。坐标系的原点,位于非洲的几内亚湾内,由此向东为经度的X轴正方向,向北为纬度的Y轴正方向。 根据不同的缩放级别,地图呈现不同的图块
  • 视觉SLAM笔记(48) 局部地图

    万次阅读 2019-11-06 08:33:21
    迭代优化的问题、特征点引入地图地图点类、关键帧、优化地图特征匹配、结果对比、缺点
  • 标注(Marker)是开发者最常使用的地图覆盖物志一,今天就来向大家介绍一些标注(Marker)的最基本使用方法! 实现目标: 1、构建基础地图页面; 2、在地图的中心点处添加 Marker; 3、实现 Marker 的点击事件响应;...
  • 基于QT的无人机仿真系统()——电子地图实现电子地图设计调用百度地图API接口地图基本功能航点绘制航线绘制航迹绘制拓展功能-视线跟随 电子地图设计 电子地图显示是系统中重要的展示模块,系统加载航线后开启...
  • )ArcGIS API For Javascript之地图操作及小部件

    万次阅读 多人点赞 2016-11-04 17:53:21
    引言 地图基本操作 1代码实现 2运行结果 3全部代码 API中的小部件 1代码实现 2代码结果绑定在DOM 3全部代码绑定在DOM 4补充将小部件绑定在地图上 5运行结果绑定在地图 6全部代码绑定在地图
  • 百度地图开发(三)之地图控制 + 定位

    万次阅读 多人点赞 2015-02-21 14:47:45
     前两篇关于百度地图的blog写的是,一些基本图层的展示 和 覆盖物的添加+地理编码和反地理编码。  接下来,这篇blog主要说一些关于地图控制方面的内容和定位功能。  百度地图提供的关于地图的操作主要有:单击...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 56,198
精华内容 22,479
关键字:

地图的四个基本特征