title: Why does ContextThemeWrapper override field "mBase" which defined in ContextWrapper?
body: <p>I am a beginer in java. Now I am learning android development and puzzled about the class definition of <strong>android.view.ContextThemeWrapper</strong>. It is a subclass of <strong>android.content.ContextWrapper</strong>. Both the two class contains a field mBase(And instance of android.content.Context). In the base class, it declared with no access modifier, but in subclass it declared with private modifier. </p>
  
  <p>So an instance of android.view.ContextThemeWrapper has two field named "mBase" indeed, only the one defined in the derived part is visible, but the one declared in the base class part is hidden.   Why  need two copy of "mBase" field in the instance of the derived class here?  In which case should I override a field defined in base class as private?</p>
  
  <p>I need your help. Thanks in advance.</p>
  
  <p>Here are the definition of the two class:</p>
  
  <p><strong>android.content.ContextWrapper:</strong></p>
  
  <pre><code> /**
   * Proxying implementation of Context that simply delegates all of its calls to
   * another Context.  Can be subclassed to modify behavior without changing
   * the original Context.
   */
  public class ContextWrapper extends Context {
      Context mBase;
  
      public ContextWrapper(Context base) {
          mBase = base;
      }
  
      /**
       * Set the base context for this ContextWrapper.  All calls will then be
       * delegated to the base context.  Throws
       * IllegalStateException if a base context has already been set.
       * 
       * @param base The new base context for this wrapper.
       */
      protected void attachBaseContext(Context base) {
          if (mBase != null) {
              throw new IllegalStateException("Base context already set");
          }
          mBase = base;
      }
  
      /**
       * @return the base context as set by the constructor or setBaseContext
       */
      public Context getBaseContext() {
          return mBase;
      }
  
      @Override
      public AssetManager getAssets() {
          return mBase.getAssets();
      }
  
      @Override
      public Resources getResources()
      {
          return mBase.getResources();
      }
  
      @Override
      public PackageManager getPackageManager() {
          return mBase.getPackageManager();
      }
  
      @Override
      public ContentResolver getContentResolver() {
          return mBase.getContentResolver();
      }
  
      @Override
      public Looper getMainLooper() {
          return mBase.getMainLooper();
      }
  
      @Override
      public Context getApplicationContext() {
          return mBase.getApplicationContext();
      }
  
      @Override
      public void setTheme(int resid) {
          mBase.setTheme(resid);
      }
  
      /** @hide */
      @Override
      public int getThemeResId() {
          return mBase.getThemeResId();
      }
  
      @Override
      public Resources.Theme getTheme() {
          return mBase.getTheme();
      }
  
      @Override
      public ClassLoader getClassLoader() {
          return mBase.getClassLoader();
      }
  
      @Override
      public String getPackageName() {
          return mBase.getPackageName();
      }
  
      @Override
      public ApplicationInfo getApplicationInfo() {
          return mBase.getApplicationInfo();
      }
  
      @Override
      public String getPackageResourcePath() {
          return mBase.getPackageResourcePath();
      }
  
      @Override
      public String getPackageCodePath() {
          return mBase.getPackageCodePath();
      }
  
      /** @hide */
      @Override
      public File getSharedPrefsFile(String name) {
          return mBase.getSharedPrefsFile(name);
      }
  
      @Override
      public SharedPreferences getSharedPreferences(String name, int mode) {
          return mBase.getSharedPreferences(name, mode);
      }
  
      @Override
      public FileInputStream openFileInput(String name)
          throws FileNotFoundException {
          return mBase.openFileInput(name);
      }
  
      @Override
      public FileOutputStream openFileOutput(String name, int mode)
          throws FileNotFoundException {
          return mBase.openFileOutput(name, mode);
      }
  
      @Override
      public boolean deleteFile(String name) {
          return mBase.deleteFile(name);
      }
  
      @Override
      public File getFileStreamPath(String name) {
          return mBase.getFileStreamPath(name);
      }
  
      @Override
      public String[] fileList() {
          return mBase.fileList();
      }
  
      @Override
      public File getFilesDir() {
          return mBase.getFilesDir();
      }
  
      @Override
      public File getExternalFilesDir(String type) {
          return mBase.getExternalFilesDir(type);
      }
  
      @Override
      public File getObbDir() {
          return mBase.getObbDir();
      }
  
      @Override
      public File getCacheDir() {
          return mBase.getCacheDir();
      }
  
      @Override
      public File getExternalCacheDir() {
          return mBase.getExternalCacheDir();
      }
  
      @Override
      public File getDir(String name, int mode) {
          return mBase.getDir(name, mode);
      }
  
      @Override
      public SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory) {
          return mBase.openOrCreateDatabase(name, mode, factory);
      }
  
      @Override
      public SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory,
              DatabaseErrorHandler errorHandler) {
          return mBase.openOrCreateDatabase(name, mode, factory, errorHandler);
      }
  
      @Override
      public boolean deleteDatabase(String name) {
          return mBase.deleteDatabase(name);
      }
  
      @Override
      public File getDatabasePath(String name) {
          return mBase.getDatabasePath(name);
      }
  
      @Override
      public String[] databaseList() {
          return mBase.databaseList();
      }
  
      @Override
      public Drawable getWallpaper() {
          return mBase.getWallpaper();
      }
  
      @Override
      public Drawable peekWallpaper() {
          return mBase.peekWallpaper();
      }
  
      @Override
      public int getWallpaperDesiredMinimumWidth() {
          return mBase.getWallpaperDesiredMinimumWidth();
      }
  
      @Override
      public int getWallpaperDesiredMinimumHeight() {
          return mBase.getWallpaperDesiredMinimumHeight();
      }
  
      @Override
      public void setWallpaper(Bitmap bitmap) throws IOException {
          mBase.setWallpaper(bitmap);
      }
  
      @Override
      public void setWallpaper(InputStream data) throws IOException {
          mBase.setWallpaper(data);
      }
  
      @Override
      public void clearWallpaper() throws IOException {
          mBase.clearWallpaper();
      }
  
      @Override
      public void startActivity(Intent intent) {
          mBase.startActivity(intent);
      }
  
      /** @hide */
      @Override
      public void startActivityAsUser(Intent intent, UserHandle user) {
          mBase.startActivityAsUser(intent, user);
      }
  
      @Override
      public void startActivity(Intent intent, Bundle options) {
          mBase.startActivity(intent, options);
      }
  
      /** @hide */
      @Override
      public void startActivityAsUser(Intent intent, Bundle options, UserHandle user) {
          mBase.startActivityAsUser(intent, options, user);
      }
  
      @Override
      public void startActivities(Intent[] intents) {
          mBase.startActivities(intents);
      }
  
      @Override
      public void startActivities(Intent[] intents, Bundle options) {
          mBase.startActivities(intents, options);
      }
  
      /** @hide */
      @Override
      public void startActivitiesAsUser(Intent[] intents, Bundle options, UserHandle userHandle) {
          mBase.startActivitiesAsUser(intents, options, userHandle);
      }
  
      @Override
      public void startIntentSender(IntentSender intent,
              Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags)
              throws IntentSender.SendIntentException {
          mBase.startIntentSender(intent, fillInIntent, flagsMask,
                  flagsValues, extraFlags);
      }
  
      @Override
      public void startIntentSender(IntentSender intent,
              Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags,
              Bundle options) throws IntentSender.SendIntentException {
          mBase.startIntentSender(intent, fillInIntent, flagsMask,
                  flagsValues, extraFlags, options);
      }
  
      @Override
      public void sendBroadcast(Intent intent) {
          mBase.sendBroadcast(intent);
      }
  
      @Override
      public void sendBroadcast(Intent intent, String receiverPermission) {
          mBase.sendBroadcast(intent, receiverPermission);
      }
  
      @Override
      public void sendOrderedBroadcast(Intent intent,
              String receiverPermission) {
          mBase.sendOrderedBroadcast(intent, receiverPermission);
      }
  
      @Override
      public void sendOrderedBroadcast(
          Intent intent, String receiverPermission, BroadcastReceiver resultReceiver,
          Handler scheduler, int initialCode, String initialData,
          Bundle initialExtras) {
          mBase.sendOrderedBroadcast(intent, receiverPermission,
                  resultReceiver, scheduler, initialCode,
                  initialData, initialExtras);
      }
  
      @Override
      public void sendBroadcastAsUser(Intent intent, UserHandle user) {
          mBase.sendBroadcastAsUser(intent, user);
      }
  
      @Override
      public void sendBroadcastAsUser(Intent intent, UserHandle user,
              String receiverPermission) {
          mBase.sendBroadcastAsUser(intent, user, receiverPermission);
      }
  
      @Override
      public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
              String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler,
              int initialCode, String initialData, Bundle initialExtras) {
          mBase.sendOrderedBroadcastAsUser(intent, user, receiverPermission, resultReceiver,
                  scheduler, initialCode, initialData, initialExtras);
      }
  
      @Override
      public void sendStickyBroadcast(Intent intent) {
          mBase.sendStickyBroadcast(intent);
      }
  
      @Override
      public void sendStickyOrderedBroadcast(
          Intent intent, BroadcastReceiver resultReceiver,
          Handler scheduler, int initialCode, String initialData,
          Bundle initialExtras) {
          mBase.sendStickyOrderedBroadcast(intent,
                  resultReceiver, scheduler, initialCode,
                  initialData, initialExtras);
      }
  
      @Override
      public void removeStickyBroadcast(Intent intent) {
          mBase.removeStickyBroadcast(intent);
      }
  
      @Override
      public void sendStickyBroadcastAsUser(Intent intent, UserHandle user) {
          mBase.sendStickyBroadcastAsUser(intent, user);
      }
  
      @Override
      public void sendStickyOrderedBroadcastAsUser(Intent intent,
              UserHandle user, BroadcastReceiver resultReceiver,
              Handler scheduler, int initialCode, String initialData,
              Bundle initialExtras) {
          mBase.sendStickyOrderedBroadcastAsUser(intent, user, resultReceiver,
                  scheduler, initialCode, initialData, initialExtras);
      }
  
      @Override
      public void removeStickyBroadcastAsUser(Intent intent, UserHandle user) {
          mBase.removeStickyBroadcastAsUser(intent, user);
      }
  
      @Override
      public Intent registerReceiver(
          BroadcastReceiver receiver, IntentFilter filter) {
          return mBase.registerReceiver(receiver, filter);
      }
  
      @Override
      public Intent registerReceiver(
          BroadcastReceiver receiver, IntentFilter filter,
          String broadcastPermission, Handler scheduler) {
          return mBase.registerReceiver(receiver, filter, broadcastPermission,
                  scheduler);
      }
  
      /** @hide */
      @Override
      public Intent registerReceiverAsUser(
          BroadcastReceiver receiver, UserHandle user, IntentFilter filter,
          String broadcastPermission, Handler scheduler) {
          return mBase.registerReceiverAsUser(receiver, user, filter, broadcastPermission,
                  scheduler);
      }
  
      @Override
      public void unregisterReceiver(BroadcastReceiver receiver) {
          mBase.unregisterReceiver(receiver);
      }
  
      @Override
      public ComponentName startService(Intent service) {
          return mBase.startService(service);
      }
  
      @Override
      public boolean stopService(Intent name) {
          return mBase.stopService(name);
      }
  
      /** @hide */
      @Override
      public ComponentName startServiceAsUser(Intent service, UserHandle user) {
          return mBase.startServiceAsUser(service, user);
      }
  
      /** @hide */
      @Override
      public boolean stopServiceAsUser(Intent name, UserHandle user) {
          return mBase.stopServiceAsUser(name, user);
      }
  
      @Override
      public boolean bindService(Intent service, ServiceConnection conn,
              int flags) {
          return mBase.bindService(service, conn, flags);
      }
  
      /** @hide */
      @Override
      public boolean bindService(Intent service, ServiceConnection conn, int flags, int userHandle) {
          return mBase.bindService(service, conn, flags, userHandle);
      }
  
      @Override
      public void unbindService(ServiceConnection conn) {
          mBase.unbindService(conn);
      }
  
      @Override
      public boolean startInstrumentation(ComponentName className,
              String profileFile, Bundle arguments) {
          return mBase.startInstrumentation(className, profileFile, arguments);
      }
  
      @Override
      public Object getSystemService(String name) {
          return mBase.getSystemService(name);
      }
  
      @Override
      public int checkPermission(String permission, int pid, int uid) {
          return mBase.checkPermission(permission, pid, uid);
      }
  
      @Override
      public int checkCallingPermission(String permission) {
          return mBase.checkCallingPermission(permission);
      }
  
      @Override
      public int checkCallingOrSelfPermission(String permission) {
          return mBase.checkCallingOrSelfPermission(permission);
      }
  
      @Override
      public void enforcePermission(
              String permission, int pid, int uid, String message) {
          mBase.enforcePermission(permission, pid, uid, message);
      }
  
      @Override
      public void enforceCallingPermission(String permission, String message) {
          mBase.enforceCallingPermission(permission, message);
      }
  
      @Override
      public void enforceCallingOrSelfPermission(
              String permission, String message) {
          mBase.enforceCallingOrSelfPermission(permission, message);
      }
  
      @Override
      public void grantUriPermission(String toPackage, Uri uri, int modeFlags) {
          mBase.grantUriPermission(toPackage, uri, modeFlags);
      }
  
      @Override
      public void revokeUriPermission(Uri uri, int modeFlags) {
          mBase.revokeUriPermission(uri, modeFlags);
      }
  
      @Override
      public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
          return mBase.checkUriPermission(uri, pid, uid, modeFlags);
      }
  
      @Override
      public int checkCallingUriPermission(Uri uri, int modeFlags) {
          return mBase.checkCallingUriPermission(uri, modeFlags);
      }
  
      @Override
      public int checkCallingOrSelfUriPermission(Uri uri, int modeFlags) {
          return mBase.checkCallingOrSelfUriPermission(uri, modeFlags);
      }
  
      @Override
      public int checkUriPermission(Uri uri, String readPermission,
              String writePermission, int pid, int uid, int modeFlags) {
          return mBase.checkUriPermission(uri, readPermission, writePermission,
                  pid, uid, modeFlags);
      }
  
      @Override
      public void enforceUriPermission(
              Uri uri, int pid, int uid, int modeFlags, String message) {
          mBase.enforceUriPermission(uri, pid, uid, modeFlags, message);
      }
  
      @Override
      public void enforceCallingUriPermission(
              Uri uri, int modeFlags, String message) {
          mBase.enforceCallingUriPermission(uri, modeFlags, message);
      }
  
      @Override
      public void enforceCallingOrSelfUriPermission(
              Uri uri, int modeFlags, String message) {
          mBase.enforceCallingOrSelfUriPermission(uri, modeFlags, message);
      }
  
      @Override
      public void enforceUriPermission(
              Uri uri, String readPermission, String writePermission,
              int pid, int uid, int modeFlags, String message) {
          mBase.enforceUriPermission(
                  uri, readPermission, writePermission, pid, uid, modeFlags,
                  message);
      }
  
      @Override
      public Context createPackageContext(String packageName, int flags)
          throws PackageManager.NameNotFoundException {
          return mBase.createPackageContext(packageName, flags);
      }
  
      /** @hide */
      @Override
      public Context createPackageContextAsUser(String packageName, int flags, UserHandle user)
              throws PackageManager.NameNotFoundException {
          return mBase.createPackageContextAsUser(packageName, flags, user);
      }
  
      @Override
      public Context createConfigurationContext(Configuration overrideConfiguration) {
          return mBase.createConfigurationContext(overrideConfiguration);
      }
  
      @Override
      public Context createDisplayContext(Display display) {
          return mBase.createDisplayContext(display);
      }
  
      @Override
      public boolean isRestricted() {
          return mBase.isRestricted();
      }
  
      /** @hide */
      @Override
      public CompatibilityInfoHolder getCompatibilityInfo(int displayId) {
          return mBase.getCompatibilityInfo(displayId);
      }
  }
  </code></pre>
  
  <p><strong>android.view.ContextThemeWrapper:</strong></p>
  
  <pre><code>/**
   * A ContextWrapper that allows you to modify the theme from what is in the 
   * wrapped context. 
   */
  public class ContextThemeWrapper extends ContextWrapper {
      private Context mBase;
      private int mThemeResource;
      private Resources.Theme mTheme;
      private LayoutInflater mInflater;
      private Configuration mOverrideConfiguration;
      private Resources mResources;
  
      public ContextThemeWrapper() {
          super(null);
      }
  
      public ContextThemeWrapper(Context base, int themeres) {
          super(base);
          mBase = base;
          mThemeResource = themeres;
      }
  
      @Override protected void attachBaseContext(Context newBase) {
          super.attachBaseContext(newBase);
          mBase = newBase;
      }
  
      /**
       * Call to set an "override configuration" on this context -- this is
       * a configuration that replies one or more values of the standard
       * configuration that is applied to the context.  See
       * {@link Context#createConfigurationContext(Configuration)} for more
       * information.
       *
       * &lt;p&gt;This method can only be called once, and must be called before any
       * calls to {@link #getResources()} are made.
       */
      public void applyOverrideConfiguration(Configuration overrideConfiguration) {
          if (mResources != null) {
              throw new IllegalStateException("getResources() has already been called");
          }
          if (mOverrideConfiguration != null) {
              throw new IllegalStateException("Override configuration has already been set");
          }
          mOverrideConfiguration = new Configuration(overrideConfiguration);
      }
  
      @Override
      public Resources getResources() {
          if (mResources != null) {
              return mResources;
          }
          if (mOverrideConfiguration == null) {
              mResources = super.getResources();
              return mResources;
          } else {
              Context resc = createConfigurationContext(mOverrideConfiguration);
              mResources = resc.getResources();
              return mResources;
          }
      }
  
      @Override public void setTheme(int resid) {
          mThemeResource = resid;
          initializeTheme();
      }
  
      /** @hide */
      @Override
      public int getThemeResId() {
          return mThemeResource;
      }
  
      @Override public Resources.Theme getTheme() {
          if (mTheme != null) {
              return mTheme;
          }
  
          mThemeResource = Resources.selectDefaultTheme(mThemeResource,
                  getApplicationInfo().targetSdkVersion);
          initializeTheme();
  
          return mTheme;
      }
  
      @Override public Object getSystemService(String name) {
          if (LAYOUT_INFLATER_SERVICE.equals(name)) {
              if (mInflater == null) {
                  mInflater = LayoutInflater.from(mBase).cloneInContext(this);
              }
              return mInflater;
          }
          return mBase.getSystemService(name);
      }
  
      /**
       * Called by {@link #setTheme} and {@link #getTheme} to apply a theme
       * resource to the current Theme object.  Can override to change the
       * default (simple) behavior.  This method will not be called in multiple
       * threads simultaneously.
       *
       * @param theme The Theme object being modified.
       * @param resid The theme style resource being applied to &lt;var&gt;theme&lt;/var&gt;.
       * @param first Set to true if this is the first time a style is being
       *              applied to &lt;var&gt;theme&lt;/var&gt;.
       */
      protected void onApplyThemeResource(Resources.Theme theme, int resid, boolean first) {
          theme.applyStyle(resid, true);
      }
  
      private void initializeTheme() {
          final boolean first = mTheme == null;
          if (first) {
              mTheme = getResources().newTheme();
              Resources.Theme theme = mBase.getTheme();
              if (theme != null) {
                  mTheme.setTo(theme);
              }
          }
          onApplyThemeResource(mTheme, mThemeResource, first);
      }
  }
  </code></pre>